// Copyright 2016 The Chromium 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/content_handler/runtime_holder.h"

#include <utility>

#include "application/lib/app/connect.h"
#include "dart/runtime/include/dart_api.h"
#include "flutter/assets/zip_asset_store.h"
#include "flutter/common/threads.h"
#include "flutter/content_handler/rasterizer.h"
#include "flutter/lib/ui/window/pointer_data_packet.h"
#include "flutter/runtime/asset_font_selector.h"
#include "flutter/runtime/dart_controller.h"
#include "lib/fidl/dart/sdk_ext/src/natives.h"
#include "lib/ftl/functional/make_copyable.h"
#include "lib/ftl/logging.h"
#include "lib/ftl/time/time_delta.h"
#include "lib/tonic/mx/mx_converter.h"
#include "lib/zip/create_unzipper.h"
#include "third_party/rapidjson/rapidjson/document.h"
#include "third_party/rapidjson/rapidjson/stringbuffer.h"
#include "third_party/rapidjson/rapidjson/writer.h"

using tonic::DartConverter;
using tonic::ToDart;

namespace flutter_runner {
namespace {

constexpr char kSnapshotKey[] = "snapshot_blob.bin";
constexpr char kAssetChannel[] = "flutter/assets";

// Maximum number of frames in flight.
constexpr int kMaxPipelineDepth = 3;

// When the max pipeline depth is exceeded, drain to this number of frames
// to recover before acknowleding the invalidation and scheduling more frames.
constexpr int kRecoveryPipelineDepth = 1;

blink::PointerData::Change GetChangeFromEventType(mozart::EventType type) {
  switch (type) {
    case mozart::EventType::POINTER_CANCEL:
      return blink::PointerData::Change::kCancel;
    case mozart::EventType::POINTER_DOWN:
      return blink::PointerData::Change::kDown;
    case mozart::EventType::POINTER_MOVE:
      return blink::PointerData::Change::kMove;
    case mozart::EventType::POINTER_UP:
      return blink::PointerData::Change::kUp;
    default:
      return blink::PointerData::Change::kCancel;
  }
}

blink::PointerData::DeviceKind GetKindFromEventKind(mozart::PointerKind kind) {
  switch (kind) {
    case mozart::PointerKind::TOUCH:
      return blink::PointerData::DeviceKind::kTouch;
    case mozart::PointerKind::MOUSE:
      return blink::PointerData::DeviceKind::kMouse;
    default:
      return blink::PointerData::DeviceKind::kTouch;
  }
}

}  // namespace

RuntimeHolder::RuntimeHolder()
    : view_listener_binding_(this),
      input_listener_binding_(this),
      weak_factory_(this) {}

RuntimeHolder::~RuntimeHolder() {
  blink::Threads::Gpu()->PostTask(
      ftl::MakeCopyable([rasterizer = std::move(rasterizer_)](){
          // Deletes rasterizer.
      }));
}

void RuntimeHolder::Init(
    fidl::InterfaceHandle<modular::ApplicationEnvironment> environment,
    fidl::InterfaceRequest<modular::ServiceProvider> outgoing_services,
    std::vector<char> bundle) {
  FTL_DCHECK(!rasterizer_);
  rasterizer_ = Rasterizer::Create();
  FTL_DCHECK(rasterizer_);

  environment_.Bind(std::move(environment));
  environment_->GetServices(fidl::GetProxy(&environment_services_));
  ConnectToService(environment_services_.get(), fidl::GetProxy(&view_manager_));
  outgoing_services_ = std::move(outgoing_services);

  InitRootBundle(std::move(bundle));
}

void RuntimeHolder::CreateView(
    const std::string& script_uri,
    fidl::InterfaceRequest<mozart::ViewOwner> view_owner_request,
    fidl::InterfaceRequest<modular::ServiceProvider> services) {
  if (view_listener_binding_.is_bound()) {
    // TODO(jeffbrown): Refactor this to support multiple view instances
    // sharing the same underlying root bundle (but with different runtimes).
    FTL_LOG(ERROR) << "The view has already been created.";
    return;
  }

  std::vector<uint8_t> snapshot;
  if (!asset_store_->GetAsBuffer(kSnapshotKey, &snapshot)) {
    FTL_LOG(ERROR) << "Unable to load snapshot from root bundle.";
    return;
  }

  mozart::ViewListenerPtr view_listener;
  view_listener_binding_.Bind(fidl::GetProxy(&view_listener));
  view_manager_->CreateView(fidl::GetProxy(&view_),
                            std::move(view_owner_request),
                            std::move(view_listener), script_uri);

  modular::ServiceProviderPtr view_services;
  view_->GetServiceProvider(GetProxy(&view_services));

  // Listen for input events.
  ConnectToService(view_services.get(), GetProxy(&input_connection_));
  mozart::InputListenerPtr input_listener;
  input_listener_binding_.Bind(GetProxy(&input_listener));
  input_connection_->SetListener(std::move(input_listener));

#if FLUTTER_ENABLE_VULKAN
  direct_input_ = std::make_unique<DirectInput>(
      [this](const blink::PointerDataPacket& packet) -> void {
        runtime_->DispatchPointerDataPacket(packet);
      });
  FTL_DCHECK(direct_input_->IsValid());
  direct_input_->WaitForReadAvailability();
#endif  // FLUTTER_ENABLE_VULKAN

  mozart::ScenePtr scene;
  view_->CreateScene(fidl::GetProxy(&scene));
  blink::Threads::Gpu()->PostTask(ftl::MakeCopyable([
    rasterizer = rasterizer_.get(), scene = std::move(scene)
  ]() mutable { rasterizer->SetScene(std::move(scene)); }));

  runtime_ = blink::RuntimeController::Create(this);
  runtime_->CreateDartController(script_uri);
  runtime_->SetViewportMetrics(viewport_metrics_);
#if FLUTTER_ENABLE_VULKAN
  direct_input_->SetViewportMetrics(viewport_metrics_);
#endif  // FLUTTER_ENABLE_VULKAN
  runtime_->dart_controller()->RunFromSnapshot(snapshot.data(),
                                               snapshot.size());
}

void RuntimeHolder::ScheduleFrame() {
  if (pending_invalidation_ || deferred_invalidation_callback_)
    return;
  pending_invalidation_ = true;
  view_->Invalidate();
}

void RuntimeHolder::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
  if (!is_ready_to_draw_)
    return;  // Only draw once per frame.
  is_ready_to_draw_ = false;

  layer_tree->set_frame_size(SkISize::Make(viewport_metrics_.physical_width,
                                           viewport_metrics_.physical_height));
  layer_tree->set_scene_version(scene_version_);

  blink::Threads::Gpu()->PostTask(ftl::MakeCopyable([
    rasterizer = rasterizer_.get(), layer_tree = std::move(layer_tree),
    self = GetWeakPtr()
  ]() mutable {
    rasterizer->Draw(std::move(layer_tree), [self]() {
      if (self)
        self->OnFrameComplete();
    });
  }));
}

void RuntimeHolder::UpdateSemantics(std::vector<blink::SemanticsNode> update) {}

void RuntimeHolder::HandlePlatformMessage(
    ftl::RefPtr<blink::PlatformMessage> message) {
  if (message->channel() == kAssetChannel) {
    HandleAssetPlatformMessage(std::move(message));
    return;
  }
  if (auto response = message->response())
    response->CompleteWithError();
}

void RuntimeHolder::DidCreateMainIsolate(Dart_Isolate isolate) {
  if (asset_store_)
    blink::AssetFontSelector::Install(asset_store_);
  InitFidlInternal();
  InitMozartInternal();
}

void RuntimeHolder::InitFidlInternal() {
  fidl::InterfaceHandle<modular::ApplicationEnvironment> environment;
  environment_->Duplicate(GetProxy(&environment));

  Dart_Handle fidl_internal = Dart_LookupLibrary(ToDart("dart:fidl.internal"));

  DART_CHECK_VALID(Dart_SetNativeResolver(
      fidl_internal, fidl::dart::NativeLookup, fidl::dart::NativeSymbol));

  DART_CHECK_VALID(Dart_SetField(
      fidl_internal, ToDart("_environment"),
      DartConverter<mx::channel>::ToDart(environment.PassHandle())));

  DART_CHECK_VALID(Dart_SetField(
      fidl_internal, ToDart("_outgoingServices"),
      DartConverter<mx::channel>::ToDart(outgoing_services_.PassChannel())));
}

void RuntimeHolder::InitMozartInternal() {
  fidl::InterfaceHandle<mozart::ViewContainer> view_container;
  view_->GetContainer(fidl::GetProxy(&view_container));

  Dart_Handle mozart_internal =
      Dart_LookupLibrary(ToDart("dart:mozart.internal"));

  DART_CHECK_VALID(Dart_SetField(
      mozart_internal, ToDart("_viewContainer"),
      DartConverter<mx::channel>::ToDart(view_container.PassHandle())));
}

void RuntimeHolder::InitRootBundle(std::vector<char> bundle) {
  root_bundle_data_ = std::move(bundle);
  asset_store_ = ftl::MakeRefCounted<blink::ZipAssetStore>(
      GetUnzipperProviderForRootBundle());
}

void RuntimeHolder::HandleAssetPlatformMessage(
    ftl::RefPtr<blink::PlatformMessage> message) {
  ftl::RefPtr<blink::PlatformMessageResponse> response = message->response();
  if (!response)
    return;
  const auto& data = message->data();
  std::string asset_name(reinterpret_cast<const char*>(data.data()),
                         data.size());
  std::vector<uint8_t> asset_data;
  if (asset_store_ && asset_store_->GetAsBuffer(asset_name, &asset_data)) {
    response->Complete(std::move(asset_data));
  } else {
    response->CompleteWithError();
  }
}

blink::UnzipperProvider RuntimeHolder::GetUnzipperProviderForRootBundle() {
  return [self = GetWeakPtr()]() {
    if (!self)
      return zip::UniqueUnzipper();
    return zip::CreateUnzipper(&self->root_bundle_data_);
  };
}

void RuntimeHolder::OnEvent(mozart::EventPtr event,
                            const OnEventCallback& callback) {
  bool handled = false;
  if (event->pointer_data) {
    blink::PointerData pointer_data;
    pointer_data.time_stamp = event->time_stamp;
    pointer_data.change = GetChangeFromEventType(event->action);
    pointer_data.kind = GetKindFromEventKind(event->pointer_data->kind);
    pointer_data.device = event->pointer_data->pointer_id;
    pointer_data.physical_x = event->pointer_data->x;
    pointer_data.physical_y = event->pointer_data->y;

    switch (pointer_data.change) {
      case blink::PointerData::Change::kDown:
        down_pointers_.insert(pointer_data.device);
        break;
      case blink::PointerData::Change::kCancel:
      case blink::PointerData::Change::kUp:
        down_pointers_.erase(pointer_data.device);
        break;
      case blink::PointerData::Change::kMove:
        if (down_pointers_.count(pointer_data.device) == 0)
          pointer_data.change = blink::PointerData::Change::kHover;
        break;
      case blink::PointerData::Change::kAdd:
      case blink::PointerData::Change::kRemove:
      case blink::PointerData::Change::kHover:
        FTL_DCHECK(down_pointers_.count(pointer_data.device) == 0);
        break;
    }

    blink::PointerDataPacket packet(1);
    packet.SetPointerData(0, pointer_data);
    runtime_->DispatchPointerDataPacket(packet);

    handled = true;
  } else if (event->key_data) {
    const char* type = nullptr;
    if (event->action == mozart::EventType::KEY_PRESSED)
      type = "keydown";
    else if (event->action == mozart::EventType::KEY_RELEASED)
      type = "keyup";

    if (type) {
      rapidjson::Document document;
      auto& allocator = document.GetAllocator();
      document.SetObject();
      document.AddMember("type", rapidjson::Value(type, strlen(type)),
                         allocator);
      document.AddMember("keymap", rapidjson::Value("fuchsia"), allocator);
      document.AddMember("hidUsage", event->key_data->hid_usage, allocator);
      document.AddMember("codePoint", event->key_data->code_point, allocator);
      document.AddMember("modifiers", event->key_data->modifiers, allocator);
      rapidjson::StringBuffer buffer;
      rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
      document.Accept(writer);

      const uint8_t* data =
          reinterpret_cast<const uint8_t*>(buffer.GetString());
      runtime_->DispatchPlatformMessage(
          ftl::MakeRefCounted<blink::PlatformMessage>(
              "flutter/keyevent",
              std::vector<uint8_t>(data, data + buffer.GetSize()), nullptr));
      handled = true;
    }
  }
  callback(handled);
}

void RuntimeHolder::OnInvalidation(mozart::ViewInvalidationPtr invalidation,
                                   const OnInvalidationCallback& callback) {
  FTL_DCHECK(invalidation);
  pending_invalidation_ = false;

  // Apply view property changes.
  if (invalidation->properties) {
    view_properties_ = std::move(invalidation->properties);
    viewport_metrics_.physical_width =
        view_properties_->view_layout->size->width;
    viewport_metrics_.physical_height =
        view_properties_->view_layout->size->height;
    viewport_metrics_.device_pixel_ratio = 2.0;
    // TODO(abarth): Use view_properties_->display_metrics->device_pixel_ratio
    // once that's reasonable.
    runtime_->SetViewportMetrics(viewport_metrics_);
#if FLUTTER_ENABLE_VULKAN
    if (direct_input_) {
      direct_input_->SetViewportMetrics(viewport_metrics_);
    }
#endif  // FLUTTER_ENABLE_VULKAN
  }

  // Remember the scene version for rendering.
  scene_version_ = invalidation->scene_version;

  // TODO(jeffbrown): Flow the frame time through the rendering pipeline.
  if (outstanding_requests_ >= kMaxPipelineDepth) {
    FTL_DCHECK(!deferred_invalidation_callback_);
    deferred_invalidation_callback_ = callback;
    return;
  }

  ++outstanding_requests_;
  BeginFrame();

  // TODO(jeffbrown): Consider running the callback earlier.
  // Note that this may result in the view processing stale view properties
  // (such as size) if it prematurely acks the frame but takes too long
  // to handle it.
  callback();
}

ftl::WeakPtr<RuntimeHolder> RuntimeHolder::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

void RuntimeHolder::BeginFrame() {
  FTL_DCHECK(outstanding_requests_ > 0);
  FTL_DCHECK(outstanding_requests_ <= kMaxPipelineDepth)
      << outstanding_requests_;

  FTL_DCHECK(!is_ready_to_draw_);
  is_ready_to_draw_ = true;
  runtime_->BeginFrame(ftl::TimePoint::Now());
  const bool was_ready_to_draw = is_ready_to_draw_;
  is_ready_to_draw_ = false;

  // If we were still ready to draw when done with the frame, that means we
  // didn't draw anything this frame and we should acknowledge the frame
  // ourselves instead of waiting for the rasterizer to acknowledge it.
  if (was_ready_to_draw)
    OnFrameComplete();
}

void RuntimeHolder::OnFrameComplete() {
  FTL_DCHECK(outstanding_requests_ > 0);
  --outstanding_requests_;

  if (deferred_invalidation_callback_ &&
      outstanding_requests_ <= kRecoveryPipelineDepth) {
    // Schedule frame first to avoid potentially generating a second
    // invalidation in case the view manager already has one pending
    // awaiting acknowledgement of the deferred invalidation.
    OnInvalidationCallback callback =
        std::move(deferred_invalidation_callback_);
    ScheduleFrame();
    callback();
  }
}

}  // namespace flutter_runner
