// Copyright (c) 2016, 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 "bin/loader.h"

#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/error_exit.h"
#include "bin/file.h"
#include "bin/gzip.h"
#include "bin/lockers.h"
#include "bin/snapshot_utils.h"
#include "bin/utils.h"
#include "include/dart_tools_api.h"
#include "platform/growable_array.h"

namespace dart {
namespace bin {

#if !defined(DART_PRECOMPILED_RUNTIME)
extern DFE dfe;
#endif

Dart_Handle Loader::InitForSnapshot(const char* snapshot_uri,
                                    IsolateData* isolate_data) {
  ASSERT(isolate_data != NULL);

  return Loader::Init(isolate_data->packages_file(),
                      DartUtils::original_working_directory, snapshot_uri);
}

// Initialize package resolution state.
Dart_Handle Loader::Init(const char* packages_file,
                         const char* working_directory,
                         const char* root_script_uri) {
  const int kNumArgs = 3;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = (packages_file == NULL)
                     ? Dart_Null()
                     : Dart_NewStringFromCString(packages_file);
  dart_args[1] = Dart_NewStringFromCString(working_directory);
  dart_args[2] = (root_script_uri == NULL)
                     ? Dart_Null()
                     : Dart_NewStringFromCString(root_script_uri);
  return Dart_Invoke(DartUtils::LookupBuiltinLib(),
                     DartUtils::NewString("_Init"), kNumArgs, dart_args);
}

#if !defined(DART_PRECOMPILED_RUNTIME)
static void MallocFinalizer(void* isolate_callback_data, void* peer) {
  free(peer);
}
#endif

Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
                                      Dart_Handle library,
                                      Dart_Handle url) {
  const char* url_string = NULL;
  Dart_Handle result = Dart_StringToCString(url, &url_string);
  if (Dart_IsError(result)) {
    return result;
  }
  if (tag == Dart_kCanonicalizeUrl) {
    Dart_Handle library_url = Dart_LibraryUrl(library);
    if (Dart_IsError(library_url)) {
      return library_url;
    }
    const char* library_url_string = NULL;
    result = Dart_StringToCString(library_url, &library_url_string);
    if (Dart_IsError(result)) {
      return result;
    }
    bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_string);
    bool is_dart_library = DartUtils::IsDartSchemeURL(library_url_string);
    if (is_dart_scheme_url || is_dart_library) {
      return url;
    }
    return Dart_DefaultCanonicalizeUrl(library_url, url);
  }
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (tag == Dart_kKernelTag) {
    uint8_t* kernel_buffer = NULL;
    intptr_t kernel_buffer_size = 0;
    if (!DFE::TryReadKernelFile(url_string, &kernel_buffer,
                                &kernel_buffer_size)) {
      return DartUtils::NewError("'%s' is not a kernel file", url_string);
    }
    result = Dart_NewExternalTypedData(Dart_TypedData_kUint8, kernel_buffer,
                                       kernel_buffer_size);
    Dart_NewFinalizableHandle(result, kernel_buffer, kernel_buffer_size,
                              MallocFinalizer);
    return result;
  }
  if (dfe.CanUseDartFrontend() && dfe.UseDartFrontend() &&
      (tag == Dart_kImportTag)) {
    // E.g., IsolateMirror.loadUri.
    char* error = NULL;
    int exit_code = 0;
    uint8_t* kernel_buffer = NULL;
    intptr_t kernel_buffer_size = -1;
    dfe.CompileAndReadScript(url_string, &kernel_buffer, &kernel_buffer_size,
                             &error, &exit_code, NULL, false);
    if (exit_code == 0) {
      return Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
    } else if (exit_code == kCompilationErrorExitCode) {
      Dart_Handle result = Dart_NewCompilationError(error);
      free(error);
      return result;
    } else {
      Dart_Handle result = Dart_NewApiError(error);
      free(error);
      return result;
    }
  }
  return DartUtils::NewError("Invalid tag : %d '%s'", tag, url_string);
#else   // !defined(DART_PRECOMPILED_RUNTIME)
  return DartUtils::NewError("Unimplemented tag : %d '%s'", tag, url_string);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
}

Dart_Handle Loader::DeferredLoadHandler(intptr_t loading_unit_id) {
  // A synchronous implementation. An asynchronous implementation would be
  // better, but the standalone embedder only implements AOT for testing.

  auto isolate_group_data =
      reinterpret_cast<IsolateGroupData*>(Dart_CurrentIsolateGroupData());
  char* unit_url = Utils::SCreate(
      "%s-%" Pd ".part.so", isolate_group_data->script_url, loading_unit_id);

  AppSnapshot* loading_unit_snapshot = Snapshot::TryReadAppSnapshot(unit_url);
  Dart_Handle result;
  if (loading_unit_snapshot != nullptr) {
    isolate_group_data->AddLoadingUnit(loading_unit_snapshot);
    const uint8_t* isolate_snapshot_data = nullptr;
    const uint8_t* isolate_snapshot_instructions = nullptr;
    const uint8_t* ignore_vm_snapshot_data;
    const uint8_t* ignore_vm_snapshot_instructions;
    loading_unit_snapshot->SetBuffers(
        &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
        &isolate_snapshot_data, &isolate_snapshot_instructions);
    result = Dart_DeferredLoadComplete(loading_unit_id, isolate_snapshot_data,
                                       isolate_snapshot_instructions);
    if (Dart_IsApiError(result)) {
      result =
          Dart_DeferredLoadCompleteError(loading_unit_id, Dart_GetError(result),
                                         /*transient*/ false);
    }
  } else {
    char* error_message = Utils::SCreate("Failed to load %s", unit_url);
    result = Dart_DeferredLoadCompleteError(loading_unit_id, error_message,
                                            /*transient*/ false);
    free(error_message);
  }

  free(unit_url);
  return result;
}

void Loader::InitOnce() {
}

}  // namespace bin
}  // namespace dart
