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

#include "runtime/dart/utils/inlines.h"
#include "third_party/dart/runtime/include/bin/dart_io_api.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/dart_microtask_queue.h"
#include "third_party/tonic/dart_state.h"
#include "third_party/tonic/typed_data/typed_list.h"

#include "builtin_libraries.h"
#include "dart_component_controller.h"
#include "logging.h"

namespace dart_runner {
namespace {

dart_utils::ElfSnapshot elf_snapshot;                     // AOT snapshot
dart_utils::MappedResource mapped_isolate_snapshot_data;  // JIT snapshot
dart_utils::MappedResource
    mapped_isolate_snapshot_instructions;  // JIT snapshot
tonic::DartLibraryNatives* service_natives = nullptr;

Dart_NativeFunction GetNativeFunction(Dart_Handle name,
                                      int argument_count,
                                      bool* auto_setup_scope) {
  dart_utils::Check(service_natives, LOG_TAG);
  return service_natives->GetNativeFunction(name, argument_count,
                                            auto_setup_scope);
}

const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
  dart_utils::Check(service_natives, LOG_TAG);
  return service_natives->GetSymbol(native_function);
}

#define SHUTDOWN_ON_ERROR(handle)           \
  if (Dart_IsError(handle)) {               \
    *error = strdup(Dart_GetError(handle)); \
    FX_LOG(ERROR, LOG_TAG, *error);         \
    Dart_ExitScope();                       \
    Dart_ShutdownIsolate();                 \
    return nullptr;                         \
  }

void NotifyServerState(Dart_NativeArguments args) {
  // NOP.
}

void Shutdown(Dart_NativeArguments args) {
  // NOP.
}

void EmbedderInformationCallback(Dart_EmbedderInformation* info) {
  info->version = DART_EMBEDDER_INFORMATION_CURRENT_VERSION;
  info->name = "dart_runner";
  info->current_rss = -1;
  info->max_rss = -1;

  zx_info_task_stats_t task_stats;
  zx_handle_t process = zx_process_self();
  zx_status_t status = zx_object_get_info(
      process, ZX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), NULL, NULL);
  if (status == ZX_OK) {
    info->current_rss =
        task_stats.mem_private_bytes + task_stats.mem_shared_bytes;
  }
}

}  // namespace

Dart_Isolate CreateServiceIsolate(const char* uri,
                                  Dart_IsolateFlags* flags,
                                  char** error) {
  Dart_SetEmbedderInformationCallback(EmbedderInformationCallback);

  const uint8_t *vmservice_data = nullptr, *vmservice_instructions = nullptr;

#if defined(AOT_RUNTIME)
  // The VM service was compiled as a separate app.
  const char* snapshot_path = "/pkg/data/vmservice_snapshot.so";
  if (elf_snapshot.Load(nullptr, snapshot_path)) {
    vmservice_data = elf_snapshot.IsolateData();
    vmservice_instructions = elf_snapshot.IsolateInstrs();
    if (vmservice_data == nullptr || vmservice_instructions == nullptr) {
      return nullptr;
    }
  } else {
    // The VM service was compiled as a separate app.
    const char* snapshot_data_path =
        "/pkg/data/vmservice_isolate_snapshot_data.bin";
    const char* snapshot_instructions_path =
        "/pkg/data/vmservice_isolate_snapshot_instructions.bin";
#else
  // The VM service is embedded in the core snapshot.
  const char* snapshot_data_path = "/pkg/data/isolate_core_snapshot_data.bin";
  const char* snapshot_instructions_path =
      "/pkg/data/isolate_core_snapshot_instructions.bin";
#endif

    if (!dart_utils::MappedResource::LoadFromNamespace(
            nullptr, snapshot_data_path, mapped_isolate_snapshot_data)) {
      *error = strdup("Failed to load snapshot for service isolate");
      FX_LOG(ERROR, LOG_TAG, *error);
      return nullptr;
    }
    if (!dart_utils::MappedResource::LoadFromNamespace(
            nullptr, snapshot_instructions_path,
            mapped_isolate_snapshot_instructions, true /* executable */)) {
      *error = strdup("Failed to load snapshot for service isolate");
      FX_LOG(ERROR, LOG_TAG, *error);
      return nullptr;
    }

    vmservice_data = mapped_isolate_snapshot_data.address();
    vmservice_instructions = mapped_isolate_snapshot_instructions.address();
#if defined(AOT_RUNTIME)
  }
#endif

  auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState());
  Dart_Isolate isolate = Dart_CreateIsolateGroup(
      uri, DART_VM_SERVICE_ISOLATE_NAME, vmservice_data, vmservice_instructions,
      nullptr /* flags */, state, state, error);
  if (!isolate) {
    FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", *error);
    return nullptr;
  }

  state->get()->SetIsolate(isolate);

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

  Dart_EnterScope();

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

  // _ip = '127.0.0.1'
  result = Dart_SetField(library, Dart_NewStringFromCString("_ip"),
                         Dart_NewStringFromCString("127.0.0.1"));
  SHUTDOWN_ON_ERROR(result);

  // _port = 0
  result = Dart_SetField(library, Dart_NewStringFromCString("_port"),
                         Dart_NewInteger(0));
  SHUTDOWN_ON_ERROR(result);

  // _autoStart = true
  result = Dart_SetField(library, Dart_NewStringFromCString("_autoStart"),
                         Dart_NewBoolean(true));
  SHUTDOWN_ON_ERROR(result);

  // _originCheckDisabled = false
  result =
      Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
                    Dart_NewBoolean(false));
  SHUTDOWN_ON_ERROR(result);

  // _authCodesDisabled = false
  result =
      Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"),
                    Dart_NewBoolean(false));
  SHUTDOWN_ON_ERROR(result);

  InitBuiltinLibrariesForIsolate(std::string(uri), nullptr, fileno(stdout),
                                 fileno(stderr), nullptr, zx::channel(), true);

  // Make runnable.
  Dart_ExitScope();
  Dart_ExitIsolate();
  *error = Dart_IsolateMakeRunnable(isolate);
  if (*error != nullptr) {
    FX_LOG(ERROR, LOG_TAG, *error);
    Dart_EnterIsolate(isolate);
    Dart_ShutdownIsolate();
    return nullptr;
  }
  return isolate;
}  // namespace dart_runner

Dart_Handle GetVMServiceAssetsArchiveCallback() {
  dart_utils::MappedResource observatory_tar;
  if (!dart_utils::MappedResource::LoadFromNamespace(
          nullptr, "/pkg/data/observatory.tar", observatory_tar)) {
    FX_LOG(ERROR, LOG_TAG, "Failed to load Observatory assets");
    return nullptr;
  }
  // TODO(rmacnak): Should we avoid copying the tar? Or does the service
  // library not hold onto it anyway?
  return tonic::DartConverter<tonic::Uint8List>::ToDart(
      reinterpret_cast<const uint8_t*>(observatory_tar.address()),
      observatory_tar.size());
}

}  // namespace dart_runner
