// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define FML_USED_ON_EMBEDDER

#include <cstdlib>
#include <cstring>
#include <iostream>

#include "flutter/assets/asset_manager.h"
#include "flutter/assets/directory_asset_bundle.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/file.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/task_runner.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/gpu/gpu_surface_software.h"
#include "third_party/dart/runtime/include/bin/dart_io_api.h"
#include "third_party/dart/runtime/include/dart_api.h"

#if defined(OS_POSIX)
#include <signal.h>
#endif  // defined(OS_POSIX)

namespace flutter {

class TesterExternalViewEmbedder : public ExternalViewEmbedder {
  // |ExternalViewEmbedder|
  SkCanvas* GetRootCanvas() override { return nullptr; }

  // |ExternalViewEmbedder|
  void CancelFrame() override {}

  // |ExternalViewEmbedder|
  void BeginFrame(
      SkISize frame_size,
      GrDirectContext* context,
      double device_pixel_ratio,
      fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override {}

  // |ExternalViewEmbedder|
  void PrerollCompositeEmbeddedView(
      int view_id,
      std::unique_ptr<EmbeddedViewParams> params) override {}

  // |ExternalViewEmbedder|
  std::vector<SkCanvas*> GetCurrentCanvases() override { return {&canvas_}; }

  // |ExternalViewEmbedder|
  SkCanvas* CompositeEmbeddedView(int view_id) override { return &canvas_; }

 private:
  SkCanvas canvas_;
};

class TesterPlatformView : public PlatformView,
                           public GPUSurfaceSoftwareDelegate {
 public:
  TesterPlatformView(Delegate& delegate, TaskRunners task_runners)
      : PlatformView(delegate, std::move(task_runners)) {}

  // |PlatformView|
  std::unique_ptr<Surface> CreateRenderingSurface() override {
    auto surface = std::make_unique<GPUSurfaceSoftware>(
        this, true /* render to surface */);
    FML_DCHECK(surface->IsValid());
    return surface;
  }

  // |GPUSurfaceSoftwareDelegate|
  sk_sp<SkSurface> AcquireBackingStore(const SkISize& size) override {
    if (sk_surface_ != nullptr &&
        SkISize::Make(sk_surface_->width(), sk_surface_->height()) == size) {
      // The old and new surface sizes are the same. Nothing to do here.
      return sk_surface_;
    }

    SkImageInfo info =
        SkImageInfo::MakeN32(size.fWidth, size.fHeight, kPremul_SkAlphaType,
                             SkColorSpace::MakeSRGB());
    sk_surface_ = SkSurface::MakeRaster(info, nullptr);

    if (sk_surface_ == nullptr) {
      FML_LOG(ERROR)
          << "Could not create backing store for software rendering.";
      return nullptr;
    }

    return sk_surface_;
  }

  // |GPUSurfaceSoftwareDelegate|
  bool PresentBackingStore(sk_sp<SkSurface> backing_store) override {
    return true;
  }

  // |PlatformView|
  std::shared_ptr<ExternalViewEmbedder> CreateExternalViewEmbedder() override {
    return external_view_embedder_;
  }

 private:
  sk_sp<SkSurface> sk_surface_ = nullptr;
  std::shared_ptr<TesterExternalViewEmbedder> external_view_embedder_ =
      std::make_shared<TesterExternalViewEmbedder>();
};

// Checks whether the engine's main Dart isolate has no pending work.  If so,
// then exit the given message loop.
class ScriptCompletionTaskObserver {
 public:
  ScriptCompletionTaskObserver(Shell& shell,
                               fml::RefPtr<fml::TaskRunner> main_task_runner,
                               bool run_forever)
      : shell_(shell),
        main_task_runner_(std::move(main_task_runner)),
        run_forever_(run_forever) {}

  int GetExitCodeForLastError() const {
    return static_cast<int>(last_error_.value_or(DartErrorCode::NoError));
  }

  void DidProcessTask() {
    last_error_ = shell_.GetUIIsolateLastError();
    if (shell_.EngineHasLivePorts()) {
      // The UI isolate still has live ports and is running. Nothing to do
      // just yet.
      return;
    }

    if (run_forever_) {
      // We need this script to run forever. We have already recorded the last
      // error. Keep going.
      return;
    }

    if (!has_terminated) {
      // Only try to terminate the loop once.
      has_terminated = true;
      fml::TaskRunner::RunNowOrPostTask(main_task_runner_, []() {
        fml::MessageLoop::GetCurrent().Terminate();
      });
    }
  }

 private:
  Shell& shell_;
  fml::RefPtr<fml::TaskRunner> main_task_runner_;
  bool run_forever_ = false;
  std::optional<DartErrorCode> last_error_;
  bool has_terminated = false;

  FML_DISALLOW_COPY_AND_ASSIGN(ScriptCompletionTaskObserver);
};

// Processes spawned via dart:io inherit their signal handling from the parent
// process. As part of spawning, the spawner blocks signals temporarily, so we
// need to explicitly unblock the signals we care about in the new process. In
// particular, we need to unblock SIGPROF for CPU profiling to work on the
// mutator thread in the main isolate in this process (threads spawned by the VM
// know about this limitation and automatically have this signal unblocked).
static void UnblockSIGPROF() {
#if defined(OS_POSIX)
  sigset_t set;
  sigemptyset(&set);
  sigaddset(&set, SIGPROF);
  pthread_sigmask(SIG_UNBLOCK, &set, NULL);
#endif  // defined(OS_POSIX)
}

int RunTester(const flutter::Settings& settings,
              bool run_forever,
              bool multithreaded) {
  const auto thread_label = "io.flutter.test.";

  // Necessary if we want to use the CPU profiler on the main isolate's mutator
  // thread.
  //
  // OSX WARNING: avoid spawning additional threads before this call due to a
  // kernel bug that may enable SIGPROF on an unintended thread in the process.
  UnblockSIGPROF();

  fml::MessageLoop::EnsureInitializedForCurrentThread();

  auto current_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();

  std::unique_ptr<ThreadHost> threadhost;
  fml::RefPtr<fml::TaskRunner> platform_task_runner;
  fml::RefPtr<fml::TaskRunner> raster_task_runner;
  fml::RefPtr<fml::TaskRunner> ui_task_runner;
  fml::RefPtr<fml::TaskRunner> io_task_runner;

  if (multithreaded) {
    threadhost = std::make_unique<ThreadHost>(
        thread_label, ThreadHost::Type::Platform | ThreadHost::Type::IO |
                          ThreadHost::Type::UI | ThreadHost::Type::RASTER);
    platform_task_runner = current_task_runner;
    raster_task_runner = threadhost->raster_thread->GetTaskRunner();
    ui_task_runner = threadhost->ui_thread->GetTaskRunner();
    io_task_runner = threadhost->io_thread->GetTaskRunner();
  } else {
    platform_task_runner = raster_task_runner = ui_task_runner =
        io_task_runner = current_task_runner;
  }

  const flutter::TaskRunners task_runners(thread_label,  // dart thread label
                                          platform_task_runner,  // platform
                                          raster_task_runner,    // raster
                                          ui_task_runner,        // ui
                                          io_task_runner         // io
  );

  Shell::CreateCallback<PlatformView> on_create_platform_view =
      [](Shell& shell) {
        return std::make_unique<TesterPlatformView>(shell,
                                                    shell.GetTaskRunners());
      };

  Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
    return std::make_unique<Rasterizer>(shell);
  };

  auto shell = Shell::Create(flutter::PlatformData(),  //
                             task_runners,             //
                             settings,                 //
                             on_create_platform_view,  //
                             on_create_rasterizer      //
  );

  if (!shell || !shell->IsSetup()) {
    FML_LOG(ERROR) << "Could not set up the shell.";
    return EXIT_FAILURE;
  }

  if (settings.application_kernel_asset.empty()) {
    FML_LOG(ERROR) << "Dart kernel file not specified.";
    return EXIT_FAILURE;
  }

  shell->GetPlatformView()->NotifyCreated();

  // Initialize default testing locales. There is no platform to
  // pass locales on the tester, so to retain expected locale behavior,
  // we emulate it in here by passing in 'en_US' and 'zh_CN' as test locales.
  const char* locale_json =
      "{\"method\":\"setLocale\",\"args\":[\"en\",\"US\",\"\",\"\",\"zh\","
      "\"CN\",\"\",\"\"]}";
  auto locale_bytes = fml::MallocMapping::Copy(
      locale_json, locale_json + std::strlen(locale_json));
  fml::RefPtr<flutter::PlatformMessageResponse> response;
  shell->GetPlatformView()->DispatchPlatformMessage(
      std::make_unique<flutter::PlatformMessage>(
          "flutter/localization", std::move(locale_bytes), response));

  std::initializer_list<fml::FileMapping::Protection> protection = {
      fml::FileMapping::Protection::kRead};
  auto main_dart_file_mapping = std::make_unique<fml::FileMapping>(
      fml::OpenFile(
          fml::paths::AbsolutePath(settings.application_kernel_asset).c_str(),
          false, fml::FilePermission::kRead),
      protection);

  auto isolate_configuration =
      IsolateConfiguration::CreateForKernel(std::move(main_dart_file_mapping));

  if (!isolate_configuration) {
    FML_LOG(ERROR) << "Could create isolate configuration.";
    return EXIT_FAILURE;
  }

  auto asset_manager = std::make_shared<flutter::AssetManager>();
  asset_manager->PushBack(std::make_unique<flutter::DirectoryAssetBundle>(
      fml::Duplicate(settings.assets_dir), true));
  asset_manager->PushBack(std::make_unique<flutter::DirectoryAssetBundle>(
      fml::OpenDirectory(settings.assets_path.c_str(), false,
                         fml::FilePermission::kRead),
      true));

  RunConfiguration run_configuration(std::move(isolate_configuration),
                                     std::move(asset_manager));

  // The script completion task observer that will be installed on the UI thread
  // that watched if the engine has any live ports.
  ScriptCompletionTaskObserver completion_observer(
      *shell,  // a valid shell
      fml::MessageLoop::GetCurrent()
          .GetTaskRunner(),  // the message loop to terminate
      run_forever            // should the exit be ignored
  );

  bool engine_did_run = false;

  fml::AutoResetWaitableEvent latch;
  auto task_observer_add = [&completion_observer]() {
    fml::MessageLoop::GetCurrent().AddTaskObserver(
        reinterpret_cast<intptr_t>(&completion_observer),
        [&completion_observer]() { completion_observer.DidProcessTask(); });
  };

  auto task_observer_remove = [&completion_observer, &latch]() {
    fml::MessageLoop::GetCurrent().RemoveTaskObserver(
        reinterpret_cast<intptr_t>(&completion_observer));
    latch.Signal();
  };

  shell->RunEngine(std::move(run_configuration),
                   [&engine_did_run, &ui_task_runner,
                    &task_observer_add](Engine::RunStatus run_status) mutable {
                     if (run_status != flutter::Engine::RunStatus::Failure) {
                       engine_did_run = true;
                       // Now that our engine is initialized we can install the
                       // ScriptCompletionTaskObserver
                       fml::TaskRunner::RunNowOrPostTask(ui_task_runner,
                                                         task_observer_add);
                     }
                   });

  flutter::ViewportMetrics metrics{};
  metrics.device_pixel_ratio = 3.0;
  metrics.physical_width = 2400.0;   // 800 at 3x resolution.
  metrics.physical_height = 1800.0;  // 600 at 3x resolution.
  shell->GetPlatformView()->SetViewportMetrics(metrics);

  // Run the message loop and wait for the script to do its thing.
  fml::MessageLoop::GetCurrent().Run();

  // Cleanup the completion observer synchronously as it is living on the
  // stack.
  fml::TaskRunner::RunNowOrPostTask(ui_task_runner, task_observer_remove);
  latch.Wait();

  if (!engine_did_run) {
    // If the engine itself didn't have a chance to run, there is no point in
    // asking it if there was an error. Signal a failure unconditionally.
    return EXIT_FAILURE;
  }

  return completion_observer.GetExitCodeForLastError();
}

}  // namespace flutter

int main(int argc, char* argv[]) {
  dart::bin::SetExecutableName(argv[0]);
  dart::bin::SetExecutableArguments(argc - 1, argv);

  auto command_line = fml::CommandLineFromArgcArgv(argc, argv);

  if (command_line.HasOption(flutter::FlagForSwitch(flutter::Switch::Help))) {
    flutter::PrintUsage("flutter_tester");
    return EXIT_SUCCESS;
  }

  auto settings = flutter::SettingsFromCommandLine(command_line);
  if (command_line.positional_args().size() > 0) {
    // The tester may not use the switch for the main dart file path. Specifying
    // it as a positional argument instead.
    settings.application_kernel_asset = command_line.positional_args()[0];
  }

  if (settings.application_kernel_asset.size() == 0) {
    FML_LOG(ERROR) << "Dart kernel file not specified.";
    return EXIT_FAILURE;
  }

  if (settings.icu_data_path.size() == 0) {
    settings.icu_data_path = "icudtl.dat";
  }

  // The tools that read logs get confused if there is a log tag specified.
  settings.log_tag = "";

  settings.log_message_callback = [](const std::string& tag,
                                     const std::string& message) {
    if (tag.size() > 0) {
      std::cout << tag << ": ";
    }
    std::cout << message << std::endl;
  };

  settings.task_observer_add = [](intptr_t key, fml::closure callback) {
    fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
  };

  settings.task_observer_remove = [](intptr_t key) {
    fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
  };

  settings.unhandled_exception_callback = [](const std::string& error,
                                             const std::string& stack_trace) {
    FML_LOG(ERROR) << "Unhandled exception" << std::endl
                   << "Exception: " << error << std::endl
                   << "Stack trace: " << stack_trace;
    ::exit(1);
    return true;
  };

  return flutter::RunTester(settings,
                            command_line.HasOption(flutter::FlagForSwitch(
                                flutter::Switch::RunForever)),
                            command_line.HasOption(flutter::FlagForSwitch(
                                flutter::Switch::ForceMultithreading)));
}
