// 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/lib/ui/window/platform_configuration.h"

#include <cstring>

#include "flutter/lib/ui/compositing/scene.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/lib/ui/window/platform_message_response_dart.h"
#include "flutter/lib/ui/window/platform_message_response_dart_port.h"
#include "flutter/lib/ui/window/viewport_metrics.h"
#include "flutter/lib/ui/window/window.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/dart_microtask_queue.h"
#include "third_party/tonic/logging/dart_invoke.h"
#include "third_party/tonic/typed_data/dart_byte_data.h"

namespace flutter {
namespace {

Dart_Handle ToByteData(const fml::Mapping& buffer) {
  return tonic::DartByteData::Create(buffer.GetMapping(), buffer.GetSize());
}

}  // namespace

PlatformConfigurationClient::~PlatformConfigurationClient() {}

PlatformConfiguration::PlatformConfiguration(
    PlatformConfigurationClient* client)
    : client_(client) {}

PlatformConfiguration::~PlatformConfiguration() {}

void PlatformConfiguration::DidCreateIsolate() {
  Dart_Handle library = Dart_LookupLibrary(tonic::ToDart("dart:ui"));

  on_error_.Set(tonic::DartState::Current(),
                Dart_GetField(library, tonic::ToDart("_onError")));
  update_locales_.Set(tonic::DartState::Current(),
                      Dart_GetField(library, tonic::ToDart("_updateLocales")));
  update_user_settings_data_.Set(
      tonic::DartState::Current(),
      Dart_GetField(library, tonic::ToDart("_updateUserSettingsData")));
  update_lifecycle_state_.Set(
      tonic::DartState::Current(),
      Dart_GetField(library, tonic::ToDart("_updateLifecycleState")));
  update_semantics_enabled_.Set(
      tonic::DartState::Current(),
      Dart_GetField(library, tonic::ToDart("_updateSemanticsEnabled")));
  update_accessibility_features_.Set(
      tonic::DartState::Current(),
      Dart_GetField(library, tonic::ToDart("_updateAccessibilityFeatures")));
  dispatch_platform_message_.Set(
      tonic::DartState::Current(),
      Dart_GetField(library, tonic::ToDart("_dispatchPlatformMessage")));
  dispatch_semantics_action_.Set(
      tonic::DartState::Current(),
      Dart_GetField(library, tonic::ToDart("_dispatchSemanticsAction")));
  begin_frame_.Set(tonic::DartState::Current(),
                   Dart_GetField(library, tonic::ToDart("_beginFrame")));
  draw_frame_.Set(tonic::DartState::Current(),
                  Dart_GetField(library, tonic::ToDart("_drawFrame")));
  report_timings_.Set(tonic::DartState::Current(),
                      Dart_GetField(library, tonic::ToDart("_reportTimings")));
  windows_.insert(std::make_pair(
      0, std::make_unique<Window>(0, ViewportMetrics{1.0, 0.0, 0.0, -1})));
}

void PlatformConfiguration::UpdateLocales(
    const std::vector<std::string>& locales) {
  std::shared_ptr<tonic::DartState> dart_state =
      update_locales_.dart_state().lock();
  if (!dart_state) {
    return;
  }

  tonic::DartState::Scope scope(dart_state);
  tonic::CheckAndHandleError(
      tonic::DartInvoke(update_locales_.Get(),
                        {
                            tonic::ToDart<std::vector<std::string>>(locales),
                        }));
}

void PlatformConfiguration::UpdateUserSettingsData(const std::string& data) {
  std::shared_ptr<tonic::DartState> dart_state =
      update_user_settings_data_.dart_state().lock();
  if (!dart_state) {
    return;
  }
  tonic::DartState::Scope scope(dart_state);

  tonic::CheckAndHandleError(tonic::DartInvoke(update_user_settings_data_.Get(),
                                               {
                                                   tonic::StdStringToDart(data),
                                               }));
}

void PlatformConfiguration::UpdateLifecycleState(const std::string& data) {
  std::shared_ptr<tonic::DartState> dart_state =
      update_lifecycle_state_.dart_state().lock();
  if (!dart_state) {
    return;
  }
  tonic::DartState::Scope scope(dart_state);
  tonic::CheckAndHandleError(tonic::DartInvoke(update_lifecycle_state_.Get(),
                                               {
                                                   tonic::StdStringToDart(data),
                                               }));
}

void PlatformConfiguration::UpdateSemanticsEnabled(bool enabled) {
  std::shared_ptr<tonic::DartState> dart_state =
      update_semantics_enabled_.dart_state().lock();
  if (!dart_state) {
    return;
  }
  tonic::DartState::Scope scope(dart_state);
  UIDartState::ThrowIfUIOperationsProhibited();

  tonic::CheckAndHandleError(tonic::DartInvoke(update_semantics_enabled_.Get(),
                                               {tonic::ToDart(enabled)}));
}

void PlatformConfiguration::UpdateAccessibilityFeatures(int32_t values) {
  std::shared_ptr<tonic::DartState> dart_state =
      update_accessibility_features_.dart_state().lock();
  if (!dart_state) {
    return;
  }
  tonic::DartState::Scope scope(dart_state);

  tonic::CheckAndHandleError(tonic::DartInvoke(
      update_accessibility_features_.Get(), {tonic::ToDart(values)}));
}

void PlatformConfiguration::DispatchPlatformMessage(
    std::unique_ptr<PlatformMessage> message) {
  std::shared_ptr<tonic::DartState> dart_state =
      dispatch_platform_message_.dart_state().lock();
  if (!dart_state) {
    FML_DLOG(WARNING)
        << "Dropping platform message for lack of DartState on channel: "
        << message->channel();
    return;
  }
  tonic::DartState::Scope scope(dart_state);
  Dart_Handle data_handle =
      (message->hasData()) ? ToByteData(message->data()) : Dart_Null();
  if (Dart_IsError(data_handle)) {
    FML_DLOG(WARNING)
        << "Dropping platform message because of a Dart error on channel: "
        << message->channel();
    return;
  }

  int response_id = 0;
  if (auto response = message->response()) {
    response_id = next_response_id_++;
    pending_responses_[response_id] = response;
  }

  tonic::CheckAndHandleError(
      tonic::DartInvoke(dispatch_platform_message_.Get(),
                        {tonic::ToDart(message->channel()), data_handle,
                         tonic::ToDart(response_id)}));
}

void PlatformConfiguration::DispatchSemanticsAction(int32_t id,
                                                    SemanticsAction action,
                                                    fml::MallocMapping args) {
  std::shared_ptr<tonic::DartState> dart_state =
      dispatch_semantics_action_.dart_state().lock();
  if (!dart_state) {
    return;
  }
  tonic::DartState::Scope scope(dart_state);

  Dart_Handle args_handle =
      (args.GetSize() <= 0) ? Dart_Null() : ToByteData(args);

  if (Dart_IsError(args_handle)) {
    return;
  }

  tonic::CheckAndHandleError(tonic::DartInvoke(
      dispatch_semantics_action_.Get(),
      {tonic::ToDart(id), tonic::ToDart(static_cast<int32_t>(action)),
       args_handle}));
}

void PlatformConfiguration::BeginFrame(fml::TimePoint frameTime,
                                       uint64_t frame_number) {
  std::shared_ptr<tonic::DartState> dart_state =
      begin_frame_.dart_state().lock();
  if (!dart_state) {
    return;
  }
  tonic::DartState::Scope scope(dart_state);

  int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds();

  tonic::CheckAndHandleError(
      tonic::DartInvoke(begin_frame_.Get(), {
                                                Dart_NewInteger(microseconds),
                                                Dart_NewInteger(frame_number),
                                            }));

  UIDartState::Current()->FlushMicrotasksNow();

  tonic::CheckAndHandleError(tonic::DartInvokeVoid(draw_frame_.Get()));
}

void PlatformConfiguration::ReportTimings(std::vector<int64_t> timings) {
  std::shared_ptr<tonic::DartState> dart_state =
      report_timings_.dart_state().lock();
  if (!dart_state) {
    return;
  }
  tonic::DartState::Scope scope(dart_state);

  Dart_Handle data_handle =
      Dart_NewTypedData(Dart_TypedData_kInt64, timings.size());

  Dart_TypedData_Type type;
  void* data = nullptr;
  intptr_t num_acquired = 0;
  FML_CHECK(!Dart_IsError(
      Dart_TypedDataAcquireData(data_handle, &type, &data, &num_acquired)));
  FML_DCHECK(num_acquired == static_cast<int>(timings.size()));

  memcpy(data, timings.data(), sizeof(int64_t) * timings.size());
  FML_CHECK(Dart_TypedDataReleaseData(data_handle));

  tonic::CheckAndHandleError(
      tonic::DartInvoke(report_timings_.Get(), {
                                                   data_handle,
                                               }));
}

void PlatformConfiguration::CompletePlatformMessageEmptyResponse(
    int response_id) {
  if (!response_id) {
    return;
  }
  auto it = pending_responses_.find(response_id);
  if (it == pending_responses_.end()) {
    return;
  }
  auto response = std::move(it->second);
  pending_responses_.erase(it);
  response->CompleteEmpty();
}

void PlatformConfiguration::CompletePlatformMessageResponse(
    int response_id,
    std::vector<uint8_t> data) {
  if (!response_id) {
    return;
  }
  auto it = pending_responses_.find(response_id);
  if (it == pending_responses_.end()) {
    return;
  }
  auto response = std::move(it->second);
  pending_responses_.erase(it);
  response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
}

void PlatformConfigurationNativeApi::Render(Scene* scene) {
  UIDartState::ThrowIfUIOperationsProhibited();
  UIDartState::Current()->platform_configuration()->client()->Render(scene);
}

void PlatformConfigurationNativeApi::SetNeedsReportTimings(bool value) {
  UIDartState::ThrowIfUIOperationsProhibited();
  UIDartState::Current()
      ->platform_configuration()
      ->client()
      ->SetNeedsReportTimings(value);
}

namespace {
Dart_Handle HandlePlatformMessage(
    UIDartState* dart_state,
    const std::string& name,
    Dart_Handle data_handle,
    const fml::RefPtr<PlatformMessageResponse>& response) {
  if (Dart_IsNull(data_handle)) {
    return dart_state->HandlePlatformMessage(
        std::make_unique<PlatformMessage>(name, response));
  } else {
    tonic::DartByteData data(data_handle);
    const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
    return dart_state->HandlePlatformMessage(std::make_unique<PlatformMessage>(
        name, fml::MallocMapping::Copy(buffer, data.length_in_bytes()),
        response));
  }
}
}  // namespace

Dart_Handle PlatformConfigurationNativeApi::SendPlatformMessage(
    const std::string& name,
    Dart_Handle callback,
    Dart_Handle data_handle) {
  UIDartState* dart_state = UIDartState::Current();

  if (!dart_state->platform_configuration()) {
    return tonic::ToDart(
        "SendPlatformMessage only works on the root isolate, see "
        "SendPortPlatformMessage.");
  }

  fml::RefPtr<PlatformMessageResponse> response;
  if (!Dart_IsNull(callback)) {
    response = fml::MakeRefCounted<PlatformMessageResponseDart>(
        tonic::DartPersistentValue(dart_state, callback),
        dart_state->GetTaskRunners().GetUITaskRunner(), name);
  }

  return HandlePlatformMessage(dart_state, name, data_handle, response);
}

Dart_Handle PlatformConfigurationNativeApi::SendPortPlatformMessage(
    const std::string& name,
    Dart_Handle identifier,
    Dart_Handle send_port,
    Dart_Handle data_handle) {
  // This can be executed on any isolate.
  UIDartState* dart_state = UIDartState::Current();

  int64_t c_send_port = tonic::DartConverter<int64_t>::FromDart(send_port);
  if (c_send_port == ILLEGAL_PORT) {
    return tonic::ToDart("Invalid port specified");
  }

  fml::RefPtr<PlatformMessageResponse> response =
      fml::MakeRefCounted<PlatformMessageResponseDartPort>(
          c_send_port, tonic::DartConverter<int64_t>::FromDart(identifier),
          name);

  return HandlePlatformMessage(dart_state, name, data_handle, response);
}

void PlatformConfigurationNativeApi::RespondToPlatformMessage(
    int response_id,
    const tonic::DartByteData& data) {
  if (Dart_IsNull(data.dart_handle())) {
    UIDartState::Current()
        ->platform_configuration()
        ->CompletePlatformMessageEmptyResponse(response_id);
  } else {
    // TODO(engine): Avoid this copy.
    const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
    UIDartState::Current()
        ->platform_configuration()
        ->CompletePlatformMessageResponse(
            response_id,
            std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()));
  }
}

void PlatformConfigurationNativeApi::SetIsolateDebugName(
    const std::string& name) {
  UIDartState::ThrowIfUIOperationsProhibited();
  UIDartState::Current()->SetDebugName(name);
}

Dart_PerformanceMode PlatformConfigurationNativeApi::current_performace_mode_ =
    Dart_PerformanceMode_Default;

Dart_PerformanceMode PlatformConfigurationNativeApi::GetDartPerformanceMode() {
  return current_performace_mode_;
}

int PlatformConfigurationNativeApi::RequestDartPerformanceMode(int mode) {
  UIDartState::ThrowIfUIOperationsProhibited();
  current_performace_mode_ = static_cast<Dart_PerformanceMode>(mode);
  return Dart_SetPerformanceMode(current_performace_mode_);
}

Dart_Handle PlatformConfigurationNativeApi::GetPersistentIsolateData() {
  UIDartState::ThrowIfUIOperationsProhibited();

  auto persistent_isolate_data = UIDartState::Current()
                                     ->platform_configuration()
                                     ->client()
                                     ->GetPersistentIsolateData();

  if (!persistent_isolate_data) {
    return Dart_Null();
  }

  return tonic::DartByteData::Create(persistent_isolate_data->GetMapping(),
                                     persistent_isolate_data->GetSize());
}

void PlatformConfigurationNativeApi::ScheduleFrame() {
  UIDartState::ThrowIfUIOperationsProhibited();
  UIDartState::Current()->platform_configuration()->client()->ScheduleFrame();
}

void PlatformConfigurationNativeApi::UpdateSemantics(SemanticsUpdate* update) {
  UIDartState::ThrowIfUIOperationsProhibited();
  UIDartState::Current()->platform_configuration()->client()->UpdateSemantics(
      update);
}

Dart_Handle PlatformConfigurationNativeApi::ComputePlatformResolvedLocale(
    Dart_Handle supportedLocalesHandle) {
  UIDartState::ThrowIfUIOperationsProhibited();
  std::vector<std::string> supportedLocales =
      tonic::DartConverter<std::vector<std::string>>::FromDart(
          supportedLocalesHandle);

  std::vector<std::string> results =
      *UIDartState::Current()
           ->platform_configuration()
           ->client()
           ->ComputePlatformResolvedLocale(supportedLocales);

  return tonic::DartConverter<std::vector<std::string>>::ToDart(results);
}

std::string PlatformConfigurationNativeApi::DefaultRouteName() {
  UIDartState::ThrowIfUIOperationsProhibited();
  return UIDartState::Current()
      ->platform_configuration()
      ->client()
      ->DefaultRouteName();
}

int64_t PlatformConfigurationNativeApi::GetRootIsolateToken() {
  UIDartState* dart_state = UIDartState::Current();
  FML_DCHECK(dart_state);
  return dart_state->GetRootIsolateToken();
}

void PlatformConfigurationNativeApi::RegisterBackgroundIsolate(
    int64_t root_isolate_token) {
  UIDartState* dart_state = UIDartState::Current();
  FML_DCHECK(dart_state && !dart_state->IsRootIsolate());
  auto platform_message_handler =
      (*static_cast<std::shared_ptr<PlatformMessageHandlerStorage>*>(
          Dart_CurrentIsolateGroupData()));
  FML_DCHECK(platform_message_handler);
  auto weak_platform_message_handler =
      platform_message_handler->GetPlatformMessageHandler(root_isolate_token);
  dart_state->SetPlatformMessageHandler(weak_platform_message_handler);
}

}  // namespace flutter
