// Copyright (c) 2024, 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.

// Executes `main` function from given Dart kernel binary (by default uses
// compiled ./hello.dart).
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <vector>
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/platform.h"
#include "include/dart_api.h"
#include "include/dart_embedder_api.h"
#include "platform/assert.h"

Dart_Handle CheckHandle(Dart_Handle handle,
                        const char* context = "unknown context") {
  if (Dart_IsError(handle)) {
    FATAL("Dart error (%s): %s", context, Dart_GetError(handle));
  }
  return handle;
}

void CheckError(bool condition, const char* error, const char* context) {
  if (!condition) {
    FATAL("Dart error (%s): %s", context, error);
  }
}

void CheckError(const char* error, const char* context) {
  if (error != nullptr) {
    FATAL("Dart error (%s): %s", context, error);
  }
}

Dart_InitializeParams CreateInitializeParams() {
  Dart_InitializeParams params;
  memset(&params, 0, sizeof(params));
  params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
  return params;
}

std::string GetExecutablePath() {
  const size_t kPathBufSize = PATH_MAX + 1;
  char executable_path[kPathBufSize] = {};

  intptr_t path_length = dart::bin::Platform::ResolveExecutablePathInto(
      executable_path, kPathBufSize);
  CheckError(path_length > 0, "empty executable path",
             "ResolveExecutablePathInfo");
  return std::string(executable_path, path_length);
}

std::string GetDefaultSnapshotPath() {
  std::string executable_path = GetExecutablePath();
  std::string directory =
      executable_path.substr(0, executable_path.find_last_of("/\\"));
  return directory + "/gen/hello_kernel.dart.snapshot";
}

std::string ReadSnapshot(std::string_view path) {
  std::string path_string{path};
  std::ifstream source_file{path_string, std::ios::binary};

  ASSERT(source_file.good());
  source_file.seekg(0, source_file.end);
  uint64_t length = source_file.tellg();
  source_file.seekg(0, source_file.beg);

  char* bytes = static_cast<char*>(std::malloc(length));
  source_file.read(bytes, length);
  auto result = std::string(bytes, length);
  std::free(bytes);
  return result;
}

Dart_Handle ToDartStringList(const std::vector<std::string>& values) {
  Dart_Handle string_type =
      CheckHandle(dart::bin::DartUtils::GetDartType("dart:core", "String"));
  Dart_Handle filler = CheckHandle(Dart_NewStringFromCString(""));

  Dart_Handle result =
      CheckHandle(Dart_NewListOfTypeFilled(string_type, filler, values.size()));
  for (size_t i = 0; i < values.size(); i++) {
    Dart_Handle element =
        CheckHandle(Dart_NewStringFromCString(values[i].c_str()));
    CheckHandle(Dart_ListSetAt(result, i, element));
  }

  return result;
}

int main(int argc, char** argv) {
  std::string snapshot_path =
      argc == 1 ? GetDefaultSnapshotPath() : std::string(argv[1]);

  std::string snapshot_name =
      snapshot_path.substr(snapshot_path.find_last_of("/\\") + 1);
  std::string snapshot_data = ReadSnapshot(snapshot_path);
  std::string snapshot_uri = "file://" + snapshot_path;
  std::cout << "Snapshot path: " << snapshot_path << std::endl;
  char* error;

  // Start Dart VM.
  bool result = dart::embedder::InitOnce(&error);
  CheckError(result, error, "dart::embedder::InitOnce");

  std::vector<const char*> flags{};
  CheckError(Dart_SetVMFlags(flags.size(), flags.data()), "Dart_SetVMFlags");

  Dart_InitializeParams initialize_params = CreateInitializeParams();
  CheckError(Dart_Initialize(&initialize_params), "Dart_Initialize");

  dart::bin::DFE dfe;
  dfe.Init();
  const uint8_t* platform_buffer = nullptr;
  intptr_t platform_buffer_size = 0;

  dfe.LoadPlatform(&platform_buffer, &platform_buffer_size);

  // Start an isolate from a platform kernel.
  Dart_IsolateFlags isolate_flags;
  Dart_IsolateFlagsInitialize(&isolate_flags);

  Dart_CreateIsolateGroupFromKernel(
      /*script_uri=*/snapshot_uri.c_str(),
      /*name=*/snapshot_name.c_str(),
      /*kernel_buffer=*/platform_buffer,
      /*kernel_buffer_size=*/platform_buffer_size,
      /*flags=*/&isolate_flags,
      /*isolate_group_data=*/nullptr,
      /*isolate_data=*/nullptr, &error);
  CheckError(error, "Dart_CreateIsolateGroupFromKernel");
  Dart_EnterScope();
  CheckHandle(dart::bin::DartUtils::PrepareForScriptLoading(
                  /*is_service_isolate=*/false, /*trace_loading=*/false),
              "PrepareForScriptLoading");

  // Load kernel snapshot to run `main` from.
  Dart_Handle library =
      CheckHandle(Dart_LoadLibraryFromKernel(
                      reinterpret_cast<const uint8_t*>(snapshot_data.c_str()),
                      snapshot_data.size()),
                  "Dart_LoadLibraryFromKernel");

  // Call main function with args.
  std::initializer_list<Dart_Handle> main_args{ToDartStringList({"universe"})};
  CheckHandle(Dart_Invoke(library, Dart_NewStringFromCString("main"), 1,
                          const_cast<Dart_Handle*>(main_args.begin())),
              "Dart_Invoke('main')");
  Dart_ExitScope();
  Dart_ShutdownIsolate();
}
