// Copyright (c) 2012, 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 <stdio.h>

#include "include/dart_api.h"

#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/platform.h"

namespace dart {
namespace bin {

Builtin::builtin_lib_props Builtin::builtin_libraries_[] = {
  /* { url_, source_, patch_url_, patch_source_, has_natives_ } */
  { DartUtils::kBuiltinLibURL, _builtin_source_paths_, NULL, NULL, true },
  { DartUtils::kIOLibURL, io_source_paths_,
    DartUtils::kIOLibPatchURL, io_patch_paths_, true },

#if defined(DART_NO_SNAPSHOT)
  // Only include these libraries in the dart_bootstrap case for now.
  { "dart:html", html_source_paths_, NULL, NULL, true },
  { "dart:html_common", html_common_source_paths_, NULL, NULL, true},
  { "dart:js", js_source_paths_, NULL, NULL, true},
  { "dart:_blink", blink_source_paths_, NULL, NULL, true },
  { "dart:indexed_db", indexeddb_source_paths_, NULL, NULL, true },
  { "cached_patches.dart", cached_patches_source_paths_, NULL, NULL, true },
  { "dart:web_gl", web_gl_source_paths_, NULL, NULL, true },
  { "metadata.dart", metadata_source_paths_, NULL, NULL, true },
  { "dart:web_sql", websql_source_paths_, NULL, NULL, true },
  { "dart:svg", svg_source_paths_, NULL, NULL, true },
  { "dart:web_audio", webaudio_source_paths_, NULL, NULL, true },
#endif  // defined(DART_NO_SNAPSHOT)

  // End marker.
  { NULL, NULL, NULL, NULL, false }
};

Dart_Port Builtin::load_port_ = ILLEGAL_PORT;
const int Builtin::num_libs_ =
    sizeof(Builtin::builtin_libraries_) / sizeof(Builtin::builtin_lib_props);

// Patch all the specified patch files in the array 'patch_files' into the
// library specified in 'library'.
static void LoadPatchFiles(Dart_Handle library,
                           const char* patch_uri,
                           const char** patch_files) {
  for (intptr_t j = 0; patch_files[j] != NULL; j += 3) {
    Dart_Handle patch_src = DartUtils::ReadStringFromFile(patch_files[j + 1]);
    if (!Dart_IsString(patch_src)) {
      // In case reading the file caused an error, use the sources directly.
      const char* source = patch_files[j + 2];
      patch_src = Dart_NewStringFromUTF8(
          reinterpret_cast<const uint8_t*>(source), strlen(source));
    }

    // Prepend the patch library URI to form a unique script URI for the patch.
    intptr_t len = snprintf(NULL, 0, "%s/%s", patch_uri, patch_files[j]);
    char* patch_filename = DartUtils::ScopedCString(len + 1);
    snprintf(patch_filename, len + 1, "%s/%s", patch_uri, patch_files[j]);
    Dart_Handle patch_file_uri = DartUtils::NewString(patch_filename);

    DART_CHECK_VALID(Dart_LibraryLoadPatch(library, patch_file_uri, patch_src));
  }
}


Dart_Handle Builtin::Source(BuiltinLibraryId id) {
  ASSERT(static_cast<int>(id) >= 0);
  ASSERT(static_cast<int>(id) < num_libs_);

  // Try to read the source using the path specified for the uri.
  const char* uri = builtin_libraries_[id].url_;
  const char** source_paths = builtin_libraries_[id].source_paths_;
  return GetSource(source_paths, uri);
}


Dart_Handle Builtin::PartSource(BuiltinLibraryId id, const char* part_uri) {
  ASSERT(static_cast<int>(id) >= 0);
  ASSERT(static_cast<int>(id) < num_libs_);

  // Try to read the source using the path specified for the uri.
  const char** source_paths = builtin_libraries_[id].source_paths_;
  return GetSource(source_paths, part_uri);
}


Dart_Handle Builtin::GetSource(const char** source_paths, const char* uri) {
  if (source_paths == NULL) {
    return Dart_Null();  // No path mapping information exists for library.
  }
  for (intptr_t i = 0; source_paths[i] != NULL; i += 3) {
    if (!strcmp(uri, source_paths[i])) {
      const char* source_path = source_paths[i + 1];
      Dart_Handle src = DartUtils::ReadStringFromFile(source_path);
      if (!Dart_IsString(src)) {
        // In case reading the file caused an error, use the sources directly.
        const char* source = source_paths[i + 2];
        src = Dart_NewStringFromUTF8(
            reinterpret_cast<const uint8_t*>(source), strlen(source));
      }
      return src;
    }
  }
  return Dart_Null();  // Uri does not exist in path mapping information.
}


void Builtin::SetNativeResolver(BuiltinLibraryId id) {
  UNREACHABLE();
}


Dart_Handle Builtin::LoadLibrary(Dart_Handle url, BuiltinLibraryId id) {
  ASSERT(static_cast<int>(id) >= 0);
  ASSERT(static_cast<int>(id) < num_libs_);

  Dart_Handle library = Dart_LoadLibrary(url, Source(id), 0, 0);
  if (!Dart_IsError(library) && (builtin_libraries_[id].has_natives_)) {
    // Setup the native resolver for built in library functions.
    DART_CHECK_VALID(
        Dart_SetNativeResolver(library, NativeLookup, NativeSymbol));
  }
  if (builtin_libraries_[id].patch_url_ != NULL) {
    ASSERT(builtin_libraries_[id].patch_paths_ != NULL);
    LoadPatchFiles(library,
                   builtin_libraries_[id].patch_url_,
                   builtin_libraries_[id].patch_paths_);
  }
  return library;
}


Builtin::BuiltinLibraryId Builtin::FindId(const char* url_string) {
  int id = 0;
  while (true) {
    if (builtin_libraries_[id].url_ == NULL) {
      return kInvalidLibrary;
    }
    if (strcmp(url_string, builtin_libraries_[id].url_) == 0) {
      return static_cast<BuiltinLibraryId>(id);
    }
    id++;
  }
}


Dart_Handle Builtin::LoadAndCheckLibrary(BuiltinLibraryId id) {
  ASSERT(static_cast<int>(id) >= 0);
  ASSERT(static_cast<int>(id) < num_libs_);

  Dart_Handle url = DartUtils::NewString(builtin_libraries_[id].url_);
  Dart_Handle library = Dart_LookupLibrary(url);
  if (Dart_IsError(library)) {
    library = LoadLibrary(url, id);
  }
  return library;
}

}  // namespace bin
}  // namespace dart
