// 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 RAPIDJSON_HAS_STDSTRING 1

#include "flutter/runtime/service_protocol.h"

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

#include "flutter/fml/posix_wrappers.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"

namespace flutter {

const std::string_view ServiceProtocol::kScreenshotExtensionName =
    "_flutter.screenshot";
const std::string_view ServiceProtocol::kScreenshotSkpExtensionName =
    "_flutter.screenshotSkp";
const std::string_view ServiceProtocol::kRunInViewExtensionName =
    "_flutter.runInView";
const std::string_view ServiceProtocol::kFlushUIThreadTasksExtensionName =
    "_flutter.flushUIThreadTasks";
const std::string_view ServiceProtocol::kSetAssetBundlePathExtensionName =
    "_flutter.setAssetBundlePath";
const std::string_view ServiceProtocol::kGetDisplayRefreshRateExtensionName =
    "_flutter.getDisplayRefreshRate";
const std::string_view ServiceProtocol::kGetSkSLsExtensionName =
    "_flutter.getSkSLs";
const std::string_view
    ServiceProtocol::kEstimateRasterCacheMemoryExtensionName =
        "_flutter.estimateRasterCacheMemory";
const std::string_view
    ServiceProtocol::kRenderFrameWithRasterStatsExtensionName =
        "_flutter.renderFrameWithRasterStats";
const std::string_view ServiceProtocol::kReloadAssetFonts =
    "_flutter.reloadAssetFonts";

static constexpr std::string_view kViewIdPrefx = "_flutterView/";
static constexpr std::string_view kListViewsExtensionName =
    "_flutter.listViews";

ServiceProtocol::ServiceProtocol()
    : endpoints_({
          // Private
          kListViewsExtensionName,

          // Public
          kScreenshotExtensionName,
          kScreenshotSkpExtensionName,
          kRunInViewExtensionName,
          kFlushUIThreadTasksExtensionName,
          kSetAssetBundlePathExtensionName,
          kGetDisplayRefreshRateExtensionName,
          kGetSkSLsExtensionName,
          kEstimateRasterCacheMemoryExtensionName,
          kRenderFrameWithRasterStatsExtensionName,
          kReloadAssetFonts,
      }),
      handlers_mutex_(fml::SharedMutex::Create()) {}

ServiceProtocol::~ServiceProtocol() {
  ToggleHooks(false);
}

void ServiceProtocol::AddHandler(Handler* handler,
                                 Handler::Description description) {
  fml::UniqueLock lock(*handlers_mutex_);
  handlers_.emplace(handler, description);
}

void ServiceProtocol::RemoveHandler(Handler* handler) {
  fml::UniqueLock lock(*handlers_mutex_);
  handlers_.erase(handler);
}

void ServiceProtocol::SetHandlerDescription(Handler* handler,
                                            Handler::Description description) {
  fml::SharedLock lock(*handlers_mutex_);
  auto it = handlers_.find(handler);
  if (it != handlers_.end()) {
    it->second.Store(description);
  }
}

void ServiceProtocol::ToggleHooks(bool set) {
  for (const auto& endpoint : endpoints_) {
    Dart_RegisterIsolateServiceRequestCallback(
        endpoint.data(),                  // method
        &ServiceProtocol::HandleMessage,  // callback
        set ? this : nullptr              // user data
    );
  }
}

static void WriteServerErrorResponse(rapidjson::Document* document,
                                     const char* message) {
  document->SetObject();
  document->AddMember("code", -32000, document->GetAllocator());
  rapidjson::Value message_value;
  message_value.SetString(message, document->GetAllocator());
  document->AddMember("message", message_value, document->GetAllocator());
}

bool ServiceProtocol::HandleMessage(const char* method,
                                    const char** param_keys,
                                    const char** param_values,
                                    intptr_t num_params,
                                    void* user_data,
                                    const char** json_object) {
  Handler::ServiceProtocolMap params;
  for (intptr_t i = 0; i < num_params; i++) {
    params[std::string_view{param_keys[i]}] = std::string_view{param_values[i]};
  }

#ifndef NDEBUG
  FML_DLOG(INFO) << "Service protcol method: " << method;
  FML_DLOG(INFO) << "Arguments: " << params.size();
  for (intptr_t i = 0; i < num_params; i++) {
    FML_DLOG(INFO) << "  " << i + 1 << ": " << param_keys[i] << " = "
                   << param_values[i];
  }
#endif  // NDEBUG

  rapidjson::Document document;
  bool result = HandleMessage(std::string_view{method},                  //
                              params,                                    //
                              static_cast<ServiceProtocol*>(user_data),  //
                              &document                                  //
  );
  rapidjson::StringBuffer buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  document.Accept(writer);
  *json_object = fml::strdup(buffer.GetString());

#ifndef NDEBUG
  FML_DLOG(INFO) << "Response: " << *json_object;
  FML_DLOG(INFO) << "RPC Result: " << result;
#endif  // NDEBUG

  return result;
}

bool ServiceProtocol::HandleMessage(std::string_view method,
                                    const Handler::ServiceProtocolMap& params,
                                    ServiceProtocol* service_protocol,
                                    rapidjson::Document* response) {
  if (service_protocol == nullptr) {
    WriteServerErrorResponse(response, "Service protocol unavailable.");
    return false;
  }

  return service_protocol->HandleMessage(method, params, response);
}

[[nodiscard]] static bool HandleMessageOnHandler(
    ServiceProtocol::Handler* handler,
    std::string_view method,
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document* document) {
  FML_DCHECK(handler);
  fml::AutoResetWaitableEvent latch;
  bool result = false;
  fml::TaskRunner::RunNowOrPostTask(
      handler->GetServiceProtocolHandlerTaskRunner(method),
      [&latch,    //
       &result,   //
       &handler,  //
       &method,   //
       &params,   //
       &document  //
  ]() {
        result =
            handler->HandleServiceProtocolMessage(method, params, document);
        latch.Signal();
      });
  latch.Wait();
  return result;
}

bool ServiceProtocol::HandleMessage(std::string_view method,
                                    const Handler::ServiceProtocolMap& params,
                                    rapidjson::Document* response) const {
  if (method == kListViewsExtensionName) {
    // So far, this is the only built-in method that does not forward to the
    // dynamic set of handlers.
    return HandleListViewsMethod(response);
  }

  fml::SharedLock lock(*handlers_mutex_);

  if (handlers_.empty()) {
    WriteServerErrorResponse(response,
                             "There are no running service protocol handlers.");
    return false;
  }

  // Find the handler by its "viewId" in the params.
  auto view_id_param_found = params.find(std::string_view{"viewId"});
  if (view_id_param_found != params.end()) {
    auto* handler = reinterpret_cast<Handler*>(std::stoull(
        view_id_param_found->second.data() + kViewIdPrefx.size(), nullptr, 16));
    auto handler_found = handlers_.find(handler);
    if (handler_found != handlers_.end()) {
      return HandleMessageOnHandler(handler, method, params, response);
    }
  }

  // Handle legacy calls that do not specify a handler in their args.
  // TODO(chinmaygarde): Deprecate these calls in the tools and remove these
  // fallbacks.
  if (method == kScreenshotExtensionName ||
      method == kScreenshotSkpExtensionName ||
      method == kFlushUIThreadTasksExtensionName) {
    return HandleMessageOnHandler(handlers_.begin()->first, method, params,
                                  response);
  }

  WriteServerErrorResponse(
      response,
      "Service protocol could not handle or find a handler for the "
      "requested method.");
  return false;
}

static std::string CreateFlutterViewID(intptr_t handler) {
  std::stringstream stream;
  stream << kViewIdPrefx << "0x" << std::hex << handler;
  return stream.str();
}

static std::string CreateIsolateID(int64_t isolate) {
  std::stringstream stream;
  stream << "isolates/" << isolate;
  return stream.str();
}

void ServiceProtocol::Handler::Description::Write(
    Handler* handler,
    rapidjson::Value& view,
    rapidjson::MemoryPoolAllocator<>& allocator) const {
  view.SetObject();
  view.AddMember("type", "FlutterView", allocator);
  view.AddMember("id", CreateFlutterViewID(reinterpret_cast<intptr_t>(handler)),
                 allocator);
  if (isolate_port != 0) {
    rapidjson::Value isolate(rapidjson::Type::kObjectType);
    {
      isolate.AddMember("type", "@Isolate", allocator);
      isolate.AddMember("fixedId", true, allocator);
      isolate.AddMember("id", CreateIsolateID(isolate_port), allocator);
      isolate.AddMember("name", isolate_name, allocator);
      isolate.AddMember("number", isolate_port, allocator);
    }
    view.AddMember("isolate", isolate, allocator);
  }
}

bool ServiceProtocol::HandleListViewsMethod(
    rapidjson::Document* response) const {
  fml::SharedLock lock(*handlers_mutex_);
  std::vector<std::pair<intptr_t, Handler::Description>> descriptions;
  for (const auto& handler : handlers_) {
    descriptions.emplace_back(reinterpret_cast<intptr_t>(handler.first),
                              handler.second.Load());
  }

  auto& allocator = response->GetAllocator();

  // Construct the response objects.
  response->SetObject();
  response->AddMember("type", "FlutterViewList", allocator);

  rapidjson::Value viewsList(rapidjson::Type::kArrayType);
  for (const auto& description : descriptions) {
    rapidjson::Value view(rapidjson::Type::kObjectType);
    description.second.Write(reinterpret_cast<Handler*>(description.first),
                             view, allocator);
    viewsList.PushBack(view, allocator);
  }

  response->AddMember("views", viewsList, allocator);

  return true;
}

}  // namespace flutter
