// 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/runtime/dart_service_isolate.h"

#include <algorithm>
#include <cstring>

#include "flutter/fml/logging.h"
#include "flutter/fml/posix_wrappers.h"
#include "flutter/runtime/embedder_resources.h"
#include "third_party/dart/runtime/include/dart_api.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/logging/dart_error.h"

#define RETURN_ERROR_HANDLE(handle) \
  if (Dart_IsError(handle)) {       \
    return handle;                  \
  }

#define SHUTDOWN_ON_ERROR(handle)                \
  if (Dart_IsError(handle)) {                    \
    *error = fml::strdup(Dart_GetError(handle)); \
    Dart_ExitScope();                            \
    Dart_ShutdownIsolate();                      \
    return false;                                \
  }

namespace flutter {
namespace {

static Dart_LibraryTagHandler g_embedder_tag_handler;
static tonic::DartLibraryNatives* g_natives;
static std::string g_observatory_uri;

Dart_NativeFunction GetNativeFunction(Dart_Handle name,
                                      int argument_count,
                                      bool* auto_setup_scope) {
  FML_CHECK(g_natives);
  return g_natives->GetNativeFunction(name, argument_count, auto_setup_scope);
}

const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
  FML_CHECK(g_natives);
  return g_natives->GetSymbol(native_function);
}

}  // namespace

std::mutex DartServiceIsolate::callbacks_mutex_;

std::set<std::unique_ptr<DartServiceIsolate::ObservatoryServerStateCallback>>
    DartServiceIsolate::callbacks_;

void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;
  std::string uri =
      tonic::DartConverter<std::string>::FromArguments(args, 0, exception);

  if (exception) {
    return;
  }

  g_observatory_uri = uri;

  // Collect callbacks to fire in a separate collection and invoke them outside
  // the lock.
  std::vector<DartServiceIsolate::ObservatoryServerStateCallback>
      callbacks_to_fire;
  {
    std::scoped_lock lock(callbacks_mutex_);
    for (auto& callback : callbacks_) {
      callbacks_to_fire.push_back(*callback.get());
    }
  }

  for (const auto& callback_to_fire : callbacks_to_fire) {
    callback_to_fire(uri);
  }
}

DartServiceIsolate::CallbackHandle DartServiceIsolate::AddServerStatusCallback(
    const DartServiceIsolate::ObservatoryServerStateCallback& callback) {
  if (!callback) {
    return 0;
  }

  auto callback_pointer =
      std::make_unique<DartServiceIsolate::ObservatoryServerStateCallback>(
          callback);

  auto handle = reinterpret_cast<CallbackHandle>(callback_pointer.get());

  {
    std::scoped_lock lock(callbacks_mutex_);
    callbacks_.insert(std::move(callback_pointer));
  }

  if (!g_observatory_uri.empty()) {
    callback(g_observatory_uri);
  }

  return handle;
}

bool DartServiceIsolate::RemoveServerStatusCallback(
    CallbackHandle callback_handle) {
  std::scoped_lock lock(callbacks_mutex_);
  auto found = std::find_if(
      callbacks_.begin(), callbacks_.end(),
      [callback_handle](const auto& item) {
        return reinterpret_cast<CallbackHandle>(item.get()) == callback_handle;
      });

  if (found == callbacks_.end()) {
    return false;
  }

  callbacks_.erase(found);
  return true;
}

void DartServiceIsolate::Shutdown(Dart_NativeArguments args) {
  // NO-OP.
}

bool DartServiceIsolate::Startup(const std::string& server_ip,
                                 intptr_t server_port,
                                 Dart_LibraryTagHandler embedder_tag_handler,
                                 bool disable_origin_check,
                                 bool disable_service_auth_codes,
                                 bool enable_service_port_fallback,
                                 char** error) {
  Dart_Isolate isolate = Dart_CurrentIsolate();
  FML_CHECK(isolate);

  // Remember the embedder's library tag handler.
  g_embedder_tag_handler = embedder_tag_handler;
  FML_CHECK(g_embedder_tag_handler);

  // Setup native entries.
  if (!g_natives) {
    g_natives = new tonic::DartLibraryNatives();
    g_natives->Register({
        {"VMServiceIO_NotifyServerState", NotifyServerState, 1, true},
        {"VMServiceIO_Shutdown", Shutdown, 0, true},
    });
  }

  Dart_Handle uri = Dart_NewStringFromCString("dart:vmservice_io");
  Dart_Handle library = Dart_LookupLibrary(uri);
  SHUTDOWN_ON_ERROR(library);
  Dart_Handle result = Dart_SetRootLibrary(library);
  SHUTDOWN_ON_ERROR(result);
  result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol);
  SHUTDOWN_ON_ERROR(result);

  library = Dart_RootLibrary();
  SHUTDOWN_ON_ERROR(library);

  // Set the HTTP server's ip.
  result = Dart_SetField(library, Dart_NewStringFromCString("_ip"),
                         Dart_NewStringFromCString(server_ip.c_str()));
  SHUTDOWN_ON_ERROR(result);
  // If we have a port specified, start the server immediately.
  bool auto_start = server_port >= 0;
  if (server_port < 0) {
    // Adjust server_port to port 0 which will result in the first available
    // port when the HTTP server is started.
    server_port = 0;
  }
  // Set the HTTP's servers port.
  result = Dart_SetField(library, Dart_NewStringFromCString("_port"),
                         Dart_NewInteger(server_port));
  SHUTDOWN_ON_ERROR(result);
  result = Dart_SetField(library, Dart_NewStringFromCString("_autoStart"),
                         Dart_NewBoolean(auto_start));
  SHUTDOWN_ON_ERROR(result);
  result =
      Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
                    Dart_NewBoolean(disable_origin_check));
  SHUTDOWN_ON_ERROR(result);
  result =
      Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"),
                    Dart_NewBoolean(disable_service_auth_codes));
  SHUTDOWN_ON_ERROR(result);
  result = Dart_SetField(
      library, Dart_NewStringFromCString("_enableServicePortFallback"),
      Dart_NewBoolean(enable_service_port_fallback));
  SHUTDOWN_ON_ERROR(result);

  // Make runnable.
  Dart_ExitScope();
  Dart_ExitIsolate();
  *error = Dart_IsolateMakeRunnable(isolate);
  if (*error) {
    Dart_EnterIsolate(isolate);
    Dart_ShutdownIsolate();
    return false;
  }
  Dart_EnterIsolate(isolate);
  Dart_EnterScope();

  return true;
}

}  // namespace flutter
