// 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.

#include "flutter/shell/common/engine.h"

#include <cstring>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "flutter/common/settings.h"
#include "flutter/fml/eintr_wrapper.h"
#include "flutter/fml/file.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/trace_event.h"
#include "flutter/fml/unique_fd.h"
#include "flutter/lib/snapshot/snapshot.h"
#include "flutter/lib/ui/text/font_collection.h"
#include "flutter/shell/common/animator.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/shell.h"
#include "rapidjson/document.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"

namespace flutter {

static constexpr char kAssetChannel[] = "flutter/assets";
static constexpr char kLifecycleChannel[] = "flutter/lifecycle";
static constexpr char kNavigationChannel[] = "flutter/navigation";
static constexpr char kLocalizationChannel[] = "flutter/localization";
static constexpr char kSettingsChannel[] = "flutter/settings";
static constexpr char kIsolateChannel[] = "flutter/isolate";

namespace {
fml::MallocMapping MakeMapping(const std::string& str) {
  return fml::MallocMapping::Copy(str.c_str(), str.length());
}
}  // namespace

Engine::Engine(
    Delegate& delegate,
    const PointerDataDispatcherMaker& dispatcher_maker,
    std::shared_ptr<fml::ConcurrentTaskRunner> image_decoder_task_runner,
    TaskRunners task_runners,
    Settings settings,
    std::unique_ptr<Animator> animator,
    fml::WeakPtr<IOManager> io_manager,
    const std::shared_ptr<FontCollection>& font_collection,
    std::unique_ptr<RuntimeController> runtime_controller)
    : delegate_(delegate),
      settings_(std::move(settings)),
      animator_(std::move(animator)),
      runtime_controller_(std::move(runtime_controller)),
      activity_running_(true),
      have_surface_(false),
      font_collection_(font_collection),
      image_decoder_(task_runners, image_decoder_task_runner, io_manager),
      task_runners_(std::move(task_runners)),
      weak_factory_(this) {
  pointer_data_dispatcher_ = dispatcher_maker(*this);
}

Engine::Engine(Delegate& delegate,
               const PointerDataDispatcherMaker& dispatcher_maker,
               DartVM& vm,
               fml::RefPtr<const DartSnapshot> isolate_snapshot,
               TaskRunners task_runners,
               const PlatformData& platform_data,
               Settings settings,
               std::unique_ptr<Animator> animator,
               fml::WeakPtr<IOManager> io_manager,
               fml::RefPtr<SkiaUnrefQueue> unref_queue,
               fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
               std::shared_ptr<VolatilePathTracker> volatile_path_tracker)
    : Engine(delegate,
             dispatcher_maker,
             vm.GetConcurrentWorkerTaskRunner(),
             task_runners,
             settings,
             std::move(animator),
             io_manager,
             std::make_shared<FontCollection>(),
             nullptr) {
  runtime_controller_ = std::make_unique<RuntimeController>(
      *this,                                 // runtime delegate
      &vm,                                   // VM
      std::move(isolate_snapshot),           // isolate snapshot
      settings_.idle_notification_callback,  // idle notification callback
      platform_data,                         // platform data
      settings_.isolate_create_callback,     // isolate create callback
      settings_.isolate_shutdown_callback,   // isolate shutdown callback
      settings_.persistent_isolate_data,     // persistent isolate data
      UIDartState::Context{
          task_runners_,                           // task runners
          std::move(snapshot_delegate),            // snapshot delegate
          std::move(io_manager),                   // io manager
          std::move(unref_queue),                  // Skia unref queue
          image_decoder_.GetWeakPtr(),             // image decoder
          image_generator_registry_.GetWeakPtr(),  // image generator registry
          settings_.advisory_script_uri,           // advisory script uri
          settings_.advisory_script_entrypoint,    // advisory script entrypoint
          std::move(volatile_path_tracker),        // volatile path tracker
      });
}

std::unique_ptr<Engine> Engine::Spawn(
    Delegate& delegate,
    const PointerDataDispatcherMaker& dispatcher_maker,
    Settings settings,
    std::unique_ptr<Animator> animator,
    const std::string& initial_route) const {
  auto result = std::make_unique<Engine>(
      /*delegate=*/delegate,
      /*dispatcher_maker=*/dispatcher_maker,
      /*image_decoder_task_runner=*/
      runtime_controller_->GetDartVM()->GetConcurrentWorkerTaskRunner(),
      /*task_runners=*/task_runners_,
      /*settings=*/settings,
      /*animator=*/std::move(animator),
      /*io_manager=*/runtime_controller_->GetIOManager(),
      /*font_collection=*/font_collection_,
      /*runtime_controller=*/nullptr);
  result->runtime_controller_ = runtime_controller_->Spawn(
      *result,                               // runtime delegate
      settings_.advisory_script_uri,         // advisory script uri
      settings_.advisory_script_entrypoint,  // advisory script entrypoint
      settings_.idle_notification_callback,  // idle notification callback
      settings_.isolate_create_callback,     // isolate create callback
      settings_.isolate_shutdown_callback,   // isolate shutdown callback
      settings_.persistent_isolate_data      // persistent isolate data
  );
  result->initial_route_ = initial_route;
  return result;
}

Engine::~Engine() = default;

fml::WeakPtr<Engine> Engine::GetWeakPtr() const {
  return weak_factory_.GetWeakPtr();
}

void Engine::SetupDefaultFontManager() {
  TRACE_EVENT0("flutter", "Engine::SetupDefaultFontManager");
  font_collection_->SetupDefaultFontManager(settings_.font_initialization_data);
}

std::shared_ptr<AssetManager> Engine::GetAssetManager() {
  return asset_manager_;
}

fml::WeakPtr<ImageGeneratorRegistry> Engine::GetImageGeneratorRegistry() {
  return image_generator_registry_.GetWeakPtr();
}

bool Engine::UpdateAssetManager(
    std::shared_ptr<AssetManager> new_asset_manager) {
  if (asset_manager_ == new_asset_manager) {
    return false;
  }

  asset_manager_ = new_asset_manager;

  if (!asset_manager_) {
    return false;
  }

  // Using libTXT as the text engine.
  font_collection_->RegisterFonts(asset_manager_);

  if (settings_.use_test_fonts) {
    font_collection_->RegisterTestFonts();
  }

  return true;
}

bool Engine::Restart(RunConfiguration configuration) {
  TRACE_EVENT0("flutter", "Engine::Restart");
  if (!configuration.IsValid()) {
    FML_LOG(ERROR) << "Engine run configuration was invalid.";
    return false;
  }
  delegate_.OnPreEngineRestart();
  runtime_controller_ = runtime_controller_->Clone();
  UpdateAssetManager(nullptr);
  return Run(std::move(configuration)) == Engine::RunStatus::Success;
}

Engine::RunStatus Engine::Run(RunConfiguration configuration) {
  if (!configuration.IsValid()) {
    FML_LOG(ERROR) << "Engine run configuration was invalid.";
    return RunStatus::Failure;
  }

  last_entry_point_ = configuration.GetEntrypoint();
  last_entry_point_library_ = configuration.GetEntrypointLibrary();

  UpdateAssetManager(configuration.GetAssetManager());

  if (runtime_controller_->IsRootIsolateRunning()) {
    return RunStatus::FailureAlreadyRunning;
  }

  // If the embedding prefetched the default font manager, then set up the
  // font manager later in the engine launch process.  This makes it less
  // likely that the setup will need to wait for the prefetch to complete.
  auto root_isolate_create_callback = [&]() {
    if (settings_.prefetched_default_font_manager) {
      SetupDefaultFontManager();
    }
  };

  if (!runtime_controller_->LaunchRootIsolate(
          settings_,                                 //
          root_isolate_create_callback,              //
          configuration.GetEntrypoint(),             //
          configuration.GetEntrypointLibrary(),      //
          configuration.TakeIsolateConfiguration())  //
  ) {
    return RunStatus::Failure;
  }

  auto service_id = runtime_controller_->GetRootIsolateServiceID();
  if (service_id.has_value()) {
    std::unique_ptr<PlatformMessage> service_id_message =
        std::make_unique<flutter::PlatformMessage>(
            kIsolateChannel, MakeMapping(service_id.value()), nullptr);
    HandlePlatformMessage(std::move(service_id_message));
  }

  return Engine::RunStatus::Success;
}

void Engine::BeginFrame(fml::TimePoint frame_time, uint64_t frame_number) {
  TRACE_EVENT0("flutter", "Engine::BeginFrame");
  runtime_controller_->BeginFrame(frame_time, frame_number);
}

void Engine::ReportTimings(std::vector<int64_t> timings) {
  TRACE_EVENT0("flutter", "Engine::ReportTimings");
  runtime_controller_->ReportTimings(std::move(timings));
}

void Engine::NotifyIdle(int64_t deadline) {
  auto trace_event = std::to_string(deadline - Dart_TimelineGetMicros());
  TRACE_EVENT1("flutter", "Engine::NotifyIdle", "deadline_now_delta",
               trace_event.c_str());
  runtime_controller_->NotifyIdle(deadline);
}

std::optional<uint32_t> Engine::GetUIIsolateReturnCode() {
  return runtime_controller_->GetRootIsolateReturnCode();
}

Dart_Port Engine::GetUIIsolateMainPort() {
  return runtime_controller_->GetMainPort();
}

std::string Engine::GetUIIsolateName() {
  return runtime_controller_->GetIsolateName();
}

bool Engine::UIIsolateHasLivePorts() {
  return runtime_controller_->HasLivePorts();
}

tonic::DartErrorHandleType Engine::GetUIIsolateLastError() {
  return runtime_controller_->GetLastError();
}

void Engine::OnOutputSurfaceCreated() {
  have_surface_ = true;
  ScheduleFrame();
}

void Engine::OnOutputSurfaceDestroyed() {
  have_surface_ = false;
  StopAnimator();
}

void Engine::SetViewportMetrics(const ViewportMetrics& metrics) {
  bool dimensions_changed =
      viewport_metrics_.physical_height != metrics.physical_height ||
      viewport_metrics_.physical_width != metrics.physical_width ||
      viewport_metrics_.device_pixel_ratio != metrics.device_pixel_ratio;
  viewport_metrics_ = metrics;
  runtime_controller_->SetViewportMetrics(viewport_metrics_);
  if (animator_) {
    if (dimensions_changed) {
      animator_->SetDimensionChangePending();
    }
    if (have_surface_) {
      ScheduleFrame();
    }
  }
}

void Engine::DispatchPlatformMessage(std::unique_ptr<PlatformMessage> message) {
  std::string channel = message->channel();
  if (channel == kLifecycleChannel) {
    if (HandleLifecyclePlatformMessage(message.get())) {
      return;
    }
  } else if (channel == kLocalizationChannel) {
    if (HandleLocalizationPlatformMessage(message.get())) {
      return;
    }
  } else if (channel == kSettingsChannel) {
    HandleSettingsPlatformMessage(message.get());
    return;
  } else if (!runtime_controller_->IsRootIsolateRunning() &&
             channel == kNavigationChannel) {
    // If there's no runtime_, we may still need to set the initial route.
    HandleNavigationPlatformMessage(std::move(message));
    return;
  }

  if (runtime_controller_->IsRootIsolateRunning() &&
      runtime_controller_->DispatchPlatformMessage(std::move(message))) {
    return;
  }

  FML_DLOG(WARNING) << "Dropping platform message on channel: " << channel;
}

bool Engine::HandleLifecyclePlatformMessage(PlatformMessage* message) {
  const auto& data = message->data();
  std::string state(reinterpret_cast<const char*>(data.GetMapping()),
                    data.GetSize());
  if (state == "AppLifecycleState.paused" ||
      state == "AppLifecycleState.detached") {
    activity_running_ = false;
    StopAnimator();
  } else if (state == "AppLifecycleState.resumed" ||
             state == "AppLifecycleState.inactive") {
    activity_running_ = true;
    StartAnimatorIfPossible();
  }

  // Always schedule a frame when the app does become active as per API
  // recommendation
  // https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive?language=objc
  if (state == "AppLifecycleState.resumed" && have_surface_) {
    ScheduleFrame();
  }
  runtime_controller_->SetLifecycleState(state);
  // Always forward these messages to the framework by returning false.
  return false;
}

bool Engine::HandleNavigationPlatformMessage(
    std::unique_ptr<PlatformMessage> message) {
  const auto& data = message->data();

  rapidjson::Document document;
  document.Parse(reinterpret_cast<const char*>(data.GetMapping()),
                 data.GetSize());
  if (document.HasParseError() || !document.IsObject()) {
    return false;
  }
  auto root = document.GetObject();
  auto method = root.FindMember("method");
  if (method->value != "setInitialRoute") {
    return false;
  }
  auto route = root.FindMember("args");
  initial_route_ = std::move(route->value.GetString());
  return true;
}

bool Engine::HandleLocalizationPlatformMessage(PlatformMessage* message) {
  const auto& data = message->data();

  rapidjson::Document document;
  document.Parse(reinterpret_cast<const char*>(data.GetMapping()),
                 data.GetSize());
  if (document.HasParseError() || !document.IsObject()) {
    return false;
  }
  auto root = document.GetObject();
  auto method = root.FindMember("method");
  if (method == root.MemberEnd()) {
    return false;
  }
  const size_t strings_per_locale = 4;
  if (method->value == "setLocale") {
    // Decode and pass the list of locale data onwards to dart.
    auto args = root.FindMember("args");
    if (args == root.MemberEnd() || !args->value.IsArray()) {
      return false;
    }

    if (args->value.Size() % strings_per_locale != 0) {
      return false;
    }
    std::vector<std::string> locale_data;
    for (size_t locale_index = 0; locale_index < args->value.Size();
         locale_index += strings_per_locale) {
      if (!args->value[locale_index].IsString() ||
          !args->value[locale_index + 1].IsString()) {
        return false;
      }
      locale_data.push_back(args->value[locale_index].GetString());
      locale_data.push_back(args->value[locale_index + 1].GetString());
      locale_data.push_back(args->value[locale_index + 2].GetString());
      locale_data.push_back(args->value[locale_index + 3].GetString());
    }

    return runtime_controller_->SetLocales(locale_data);
  }
  return false;
}

void Engine::HandleSettingsPlatformMessage(PlatformMessage* message) {
  const auto& data = message->data();
  std::string jsonData(reinterpret_cast<const char*>(data.GetMapping()),
                       data.GetSize());
  if (runtime_controller_->SetUserSettingsData(std::move(jsonData)) &&
      have_surface_) {
    ScheduleFrame();
  }
}

void Engine::DispatchPointerDataPacket(
    std::unique_ptr<PointerDataPacket> packet,
    uint64_t trace_flow_id) {
  TRACE_EVENT0("flutter", "Engine::DispatchPointerDataPacket");
  TRACE_FLOW_STEP("flutter", "PointerEvent", trace_flow_id);
  pointer_data_dispatcher_->DispatchPacket(std::move(packet), trace_flow_id);
}

void Engine::DispatchKeyDataPacket(std::unique_ptr<KeyDataPacket> packet,
                                   KeyDataResponse callback) {
  TRACE_EVENT0("flutter", "Engine::DispatchKeyDataPacket");
  if (runtime_controller_) {
    runtime_controller_->DispatchKeyDataPacket(*packet, std::move(callback));
  }
}

void Engine::DispatchSemanticsAction(int id,
                                     SemanticsAction action,
                                     fml::MallocMapping args) {
  runtime_controller_->DispatchSemanticsAction(id, action, std::move(args));
}

void Engine::SetSemanticsEnabled(bool enabled) {
  runtime_controller_->SetSemanticsEnabled(enabled);
}

void Engine::SetAccessibilityFeatures(int32_t flags) {
  runtime_controller_->SetAccessibilityFeatures(flags);
}

void Engine::StopAnimator() {
  animator_->Stop();
}

void Engine::StartAnimatorIfPossible() {
  if (activity_running_ && have_surface_) {
    animator_->Start();
  }
}

std::string Engine::DefaultRouteName() {
  if (!initial_route_.empty()) {
    return initial_route_;
  }
  return "/";
}

void Engine::ScheduleFrame(bool regenerate_layer_tree) {
  StartAnimatorIfPossible();
  animator_->RequestFrame(regenerate_layer_tree);
}

void Engine::Render(std::unique_ptr<flutter::LayerTree> layer_tree) {
  if (!layer_tree) {
    return;
  }

  // Ensure frame dimensions are sane.
  if (layer_tree->frame_size().isEmpty() ||
      layer_tree->device_pixel_ratio() <= 0.0f) {
    return;
  }

  animator_->Render(std::move(layer_tree));
}

void Engine::UpdateSemantics(SemanticsNodeUpdates update,
                             CustomAccessibilityActionUpdates actions) {
  delegate_.OnEngineUpdateSemantics(std::move(update), std::move(actions));
}

void Engine::HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) {
  if (message->channel() == kAssetChannel) {
    HandleAssetPlatformMessage(std::move(message));
  } else {
    delegate_.OnEngineHandlePlatformMessage(std::move(message));
  }
}

void Engine::OnRootIsolateCreated() {
  delegate_.OnRootIsolateCreated();
}

void Engine::UpdateIsolateDescription(const std::string isolate_name,
                                      int64_t isolate_port) {
  delegate_.UpdateIsolateDescription(isolate_name, isolate_port);
}

std::unique_ptr<std::vector<std::string>> Engine::ComputePlatformResolvedLocale(
    const std::vector<std::string>& supported_locale_data) {
  return delegate_.ComputePlatformResolvedLocale(supported_locale_data);
}

void Engine::SetNeedsReportTimings(bool needs_reporting) {
  delegate_.SetNeedsReportTimings(needs_reporting);
}

FontCollection& Engine::GetFontCollection() {
  return *font_collection_;
}

void Engine::DoDispatchPacket(std::unique_ptr<PointerDataPacket> packet,
                              uint64_t trace_flow_id) {
  animator_->EnqueueTraceFlowId(trace_flow_id);
  if (runtime_controller_) {
    runtime_controller_->DispatchPointerDataPacket(*packet);
  }
}

void Engine::ScheduleSecondaryVsyncCallback(uintptr_t id,
                                            const fml::closure& callback) {
  animator_->ScheduleSecondaryVsyncCallback(id, callback);
}

void Engine::HandleAssetPlatformMessage(
    std::unique_ptr<PlatformMessage> message) {
  fml::RefPtr<PlatformMessageResponse> response = message->response();
  if (!response) {
    return;
  }
  const auto& data = message->data();
  std::string asset_name(reinterpret_cast<const char*>(data.GetMapping()),
                         data.GetSize());

  if (asset_manager_) {
    std::unique_ptr<fml::Mapping> asset_mapping =
        asset_manager_->GetAsMapping(asset_name);
    if (asset_mapping) {
      response->Complete(std::move(asset_mapping));
      return;
    }
  }

  response->CompleteEmpty();
}

const std::string& Engine::GetLastEntrypoint() const {
  return last_entry_point_;
}

const std::string& Engine::GetLastEntrypointLibrary() const {
  return last_entry_point_library_;
}

// |RuntimeDelegate|
void Engine::RequestDartDeferredLibrary(intptr_t loading_unit_id) {
  return delegate_.RequestDartDeferredLibrary(loading_unit_id);
}

void Engine::LoadDartDeferredLibrary(
    intptr_t loading_unit_id,
    std::unique_ptr<const fml::Mapping> snapshot_data,
    std::unique_ptr<const fml::Mapping> snapshot_instructions) {
  if (runtime_controller_->IsRootIsolateRunning()) {
    runtime_controller_->LoadDartDeferredLibrary(
        loading_unit_id, std::move(snapshot_data),
        std::move(snapshot_instructions));
  } else {
    LoadDartDeferredLibraryError(loading_unit_id, "No running root isolate.",
                                 true);
  }
}

void Engine::LoadDartDeferredLibraryError(intptr_t loading_unit_id,
                                          const std::string error_message,
                                          bool transient) {
  if (runtime_controller_->IsRootIsolateRunning()) {
    runtime_controller_->LoadDartDeferredLibraryError(loading_unit_id,
                                                      error_message, transient);
  }
}

}  // namespace flutter
