// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "engine/engine.h"
#include <errno.h>
#include <memory>
#include "bin/dartutils.h"
#include "include/dart_api.h"
#include "include/dart_embedder_api.h"
#include "include/dart_engine.h"
#include "platform/lockers.h"
#include "platform/syslog.h"
#include "platform/utils.h"

namespace dart {
namespace engine {

constexpr char kRunPendingImmediateCallback[] = "_runPendingImmediateCallback";

using platform::MutexLocker;

Engine* Engine::instance() {
  static Engine* instance = new Engine();
  return instance;
}

DartEngine_SnapshotData Engine::KernelFromFile(const char* path, char** error) {
  DartEngine_SnapshotData result;
  result.kind = DartEngine_SnapshotKind_Kernel;
  result.script_uri = Utils::SCreate("file://%s", path);
  FILE* file = fopen(path, "rb");
  if (file == nullptr) {
    *error = Utils::SCreate("Error %d", errno);
    return result;
  }

  fseek(file, 0, SEEK_END);
  intptr_t size = ftell(file);
  rewind(file);

  char* buffer = reinterpret_cast<char*>(malloc(sizeof(char) * size));

  intptr_t bytes_read = fread(buffer, 1, size, file);
  fclose(file);
  if (bytes_read != size) {
    free(buffer);
    *error = Utils::SCreate("Error reading %s: read %zu bytes instead of %zu",
                            path, bytes_read, size);
    return result;
  }

  result.kernel_buffer_size = size;
  result.kernel_buffer = reinterpret_cast<uint8_t*>(buffer);

  {
    MutexLocker ml(&engine_state_);
    owned_snapshots_.emplace_back(result);
  }

  return result;
}

DartEngine_SnapshotData Engine::AotFromFile(const char* path, char** error) {
  DartEngine_SnapshotData result;
  result.kind = DartEngine_SnapshotKind_AOT;
  result.script_uri = Utils::SCreate("file://%s", path);

  void* library =
      Utils::LoadDynamicLibrary(path, /*search_dll_load_dir=*/false, error);

  result.vm_snapshot_data = reinterpret_cast<const uint8_t*>(
      Utils::ResolveSymbolInDynamicLibrary(library, kVmSnapshotDataCSymbol));
  result.vm_snapshot_instructions =
      reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
          library, kVmSnapshotInstructionsCSymbol));
  result.vm_isolate_data =
      reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
          library, kIsolateSnapshotDataCSymbol));
  result.vm_isolate_instructions =
      reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
          library, kIsolateSnapshotInstructionsCSymbol));

  if (*error != nullptr) {
    return result;
  }

  {
    MutexLocker ml(&engine_state_);
    loaded_libraries_.emplace_back(library);
    owned_snapshots_.emplace_back(result);
  }

  return result;
}

namespace {
Dart_InitializeParams CreateInitializeParams() {
  Dart_InitializeParams params;
  memset(&params, 0, sizeof(params));
  params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
  params.shutdown_isolate = nullptr;
  params.create_group = nullptr;
  return params;
}
}  // namespace

bool Engine::Initialize(char** error) {
  if (initialized_) {
    return true;
  }
  MutexLocker ml(&engine_lifecycle_);

  if (initialized_) {
    return true;
  }
  if (!dart::embedder::InitOnce(error)) {
    return false;
  }

  std::vector<const char*> flags{};
  if (Dart_IsPrecompiledRuntime()) {
    flags.push_back("--precompilation");
  }
  *error = Dart_SetVMFlags(flags.size(), flags.data());

  if (*error != nullptr) {
    return false;
  }

  initialized_ = true;

  return true;
}

Dart_Isolate Engine::StartIsolate(DartEngine_SnapshotData snapshot,
                                  char** error) {
  if (Dart_IsPrecompiledRuntime() &&
      snapshot.kind != DartEngine_SnapshotKind_AOT) {
    *error = Utils::StrDup("AOT Dart VM supports only AOT snapshots");
    return nullptr;
  }

  if (!Dart_IsPrecompiledRuntime() &&
      snapshot.kind != DartEngine_SnapshotKind_Kernel) {
    *error = Utils::StrDup("AOT Dart VM supports only AOT snapshots");
    return nullptr;
  }

  if (!first_isolate_started_) {
    // This is a part of an initialization, so using engine_lifecycle_ mutex
    // here.
    MutexLocker ml(&engine_lifecycle_);
    if (!first_isolate_started_) {
      Dart_InitializeParams initialize_params = CreateInitializeParams();

      if (Dart_IsPrecompiledRuntime()) {
        initialize_params.vm_snapshot_data = snapshot.vm_snapshot_data;
        initialize_params.vm_snapshot_instructions =
            snapshot.vm_snapshot_instructions;
      }
      *error = Dart_Initialize(&initialize_params);
      if (*error != nullptr) {
        return nullptr;
      }
      first_isolate_started_ = true;
    }
  }

  // Now we can start an isolate.
  Dart_IsolateFlags isolate_flags;
  Dart_IsolateFlagsInitialize(&isolate_flags);

  Dart_Isolate isolate;
  if (Dart_IsPrecompiledRuntime()) {
    // Automatically sets the root library for the isolate.
    isolate = Dart_CreateIsolateGroup(
        snapshot.script_uri, strrchr(snapshot.script_uri, '/'),
        snapshot.vm_isolate_data, snapshot.vm_isolate_instructions,
        &isolate_flags, nullptr, nullptr, error);
  } else {
    isolate = Dart_CreateIsolateGroupFromKernel(
        snapshot.script_uri, snapshot.script_uri, snapshot.kernel_buffer,
        snapshot.kernel_buffer_size, &isolate_flags, nullptr, nullptr, error);
  }

  if (*error != nullptr) {
    return nullptr;
  }

  Dart_SetMessageNotifyCallback(Engine::MessageNotifyCallback);

  Dart_EnterScope();

  // In fact, this call initializes core libraries, (e.g. `print` doesn't work
  // without it).
  Dart_Handle core_libs_result = bin::DartUtils::PrepareForScriptLoading(
      false, false, /*flag_profile_microtasks=*/false);
  if (Dart_IsError(core_libs_result)) {
    *error = Utils::StrDup(Dart_GetError(core_libs_result));
    Dart_ShutdownIsolate();
    return nullptr;
  }

  if (!Dart_IsPrecompiledRuntime()) {
    // In kernel mode, also call LoadScriptFromKernel to set the root library.
    // Technically, the library is already loaded after
    // Dart_CreateIsolateGroupFromKernel, the problem is we don't know its URI
    // (it is not related to snapshot->uri and depends on where the kernel
    // snapshot was built, e.g. file:///Users/user/samples/hello.dart)
    Dart_Handle library = Dart_LoadScriptFromKernel(
        snapshot.kernel_buffer, snapshot.kernel_buffer_size);

    if (Dart_IsError(library)) {
      *error = Utils::StrDup(Dart_GetError(library));
      Dart_ShutdownIsolate();
      return nullptr;
    }
  }

  Dart_Handle isolate_library = Dart_LookupLibrary(
      Dart_NewStringFromCString(bin::DartUtils::kIsolateLibURL));
  if (Dart_IsError(isolate_library)) {
    *error = Utils::StrDup(Dart_GetError(isolate_library));
    Dart_ShutdownIsolate();
    return nullptr;
  }

  std::shared_ptr<Engine::IsolateData> isolate_data = DataForIsolate(isolate);
  isolate_data->isolate_library = Dart_NewPersistentHandle(isolate_library);
  isolate_data->drain_microtasks_function_name = Dart_NewPersistentHandle(
      Dart_NewStringFromCString(kRunPendingImmediateCallback));
  isolate_data->scheduler.context = nullptr;
  isolate_data->scheduler.schedule_callback = nullptr;

  Dart_ExitScope();
  Dart_ExitIsolate();
  is_running_ = true;
  isolates_.emplace_back(isolate);
  return isolate;
}

void Engine::MessageNotifyCallback(Dart_Isolate isolate) {
  Engine::instance()->NotifyMessage(isolate);
}

void Engine::Shutdown() {
  MutexLocker shutdown_locker(&engine_lifecycle_);

  is_running_ = false;
  for (auto isolate : isolates_) {
    std::shared_ptr<Engine::IsolateData> isolate_data = DataForIsolate(isolate);
    LockIsolate(isolate);
    Dart_EnterIsolate(isolate);
    Dart_SetMessageNotifyCallback(nullptr);
    Dart_DeletePersistentHandle(isolate_data->isolate_library);
    Dart_DeletePersistentHandle(isolate_data->drain_microtasks_function_name);
    Dart_ShutdownIsolate();
    UnlockIsolate(isolate);
  }

  MutexLocker state_locker(&engine_state_);
  for (auto& snapshot : owned_snapshots_) {
    switch (snapshot.kind) {
      case DartEngine_SnapshotKind_Kernel:
        free(const_cast<uint8_t*>(snapshot.kernel_buffer));
        break;
      case DartEngine_SnapshotKind_AOT:
        // No need to free AOT buffers loaded from dynamic library.
        break;
      default:
        Syslog::PrintErr("Unsupported SnapshotKind: %d\n", snapshot.kind);
        break;
    }
    free(const_cast<char*>(snapshot.script_uri));
  }
}

void Engine::HandleMessage(Dart_Isolate isolate) {
  LockIsolate(isolate);
  Dart_EnterIsolate(isolate);
  Dart_EnterScope();

  Dart_Handle handle_result = Dart_HandleMessage();

  if (Dart_IsError(handle_result)) {
    if (handle_message_error_callback_ != nullptr) {
      handle_message_error_callback_(handle_result, isolate);
    } else {
      Syslog::PrintErr("Error handling isolate message: %s",
                       Dart_GetError(handle_result));
    }
  }

  Dart_ExitScope();
  Dart_ExitIsolate();
  UnlockIsolate(isolate);
}

Dart_Handle Engine::DrainMicrotasksQueue() {
  std::shared_ptr<Engine::IsolateData> isolate_data =
      DataForIsolate(Dart_CurrentIsolate());
  return Dart_Invoke(isolate_data->isolate_library,
                     isolate_data->drain_microtasks_function_name, 0, nullptr);
}

std::shared_ptr<Engine::IsolateData> Engine::DataForIsolate(
    Dart_Isolate isolate) {
  MutexLocker ml(&engine_state_);
  auto it = isolate_data_.find(isolate);
  if (it == isolate_data_.end()) {
    it = isolate_data_.emplace(isolate, std::make_shared<Engine::IsolateData>())
             .first;
  }
  return it->second;
}

void Engine::LockIsolate(Dart_Isolate isolate) {
  DataForIsolate(isolate)->mutex.Lock();
}

void Engine::UnlockIsolate(Dart_Isolate isolate) {
  DataForIsolate(isolate)->mutex.Unlock();
}

void Engine::NotifyMessage(Dart_Isolate isolate) {
  if (!engine_lifecycle_.TryLock() || !is_running_) {
    // Shutdown is in progress or complete.
    //
    // Used to prevent a potential deadlock during shutdown.
    //
    // If Engine::MessageNotifyCallback is waiting for Engine::HandleMessage
    // completion (which happens in samples/embedder/run_timer_async), and
    // another thread calls Engine::Shutdown, the deadlock may occur:
    //
    // 1. MessageNotifyCallback thread owns PortMap::mutex_ (through
    // PortMap::PostMessage) and wants to lock an isolate (via
    // Engine::LockIsolate).
    // 2. Shutdown thread owns an isolate lock and wants to lock PortMap::mutex_
    // (inside Dart_ShutdownIsolate call).
    //
    // This mutex is used to prevent it:
    // - Engine::Shutdown locks it.
    // - Engine::NotifyMessage tries to lock it, and treats lock failure as
    //   shutdown in progress.
    return;
  }

  DartEngine_MessageScheduler scheduler = DataForIsolate(isolate)->scheduler;

  if (scheduler.schedule_callback == nullptr) {
    scheduler = default_scheduler_;
  }
  if (scheduler.schedule_callback == nullptr) {
    engine_lifecycle_.Unlock();
    return;
  }
  scheduler.schedule_callback(isolate, scheduler.context);
  engine_lifecycle_.Unlock();
}

void Engine::SetHandleMessageErrorCallback(
    DartEngine_HandleMessageErrorCallback callback) {
  handle_message_error_callback_ = callback;
}

void Engine::SetDefaultMessageScheduler(DartEngine_MessageScheduler scheduler) {
  default_scheduler_ = scheduler;
}

void Engine::SetMessageScheduler(DartEngine_MessageScheduler scheduler,
                                 Dart_Isolate isolate) {
  DataForIsolate(isolate)->scheduler = scheduler;
}

}  // namespace engine
}  // namespace dart
