// Copyright 2016 The Fuchsia 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 "tonic/file_loader/file_loader.h"

#include <iostream>
#include <memory>
#include <utility>

#include "filesystem/file.h"
#include "filesystem/path.h"
#include "filesystem/portable_unistd.h"
#include "tonic/common/macros.h"
#include "tonic/converter/dart_converter.h"
#include "tonic/parsers/packages_map.h"
#include "tonic/platform/platform_utils.h"

namespace tonic {
namespace {

constexpr char kDartScheme[] = "dart:";

constexpr char kFileScheme[] = "file:";
constexpr size_t kFileSchemeLength = sizeof(kFileScheme) - 1;

constexpr char kPackageScheme[] = "package:";
constexpr size_t kPackageSchemeLength = sizeof(kPackageScheme) - 1;

// Extract the scheme prefix ('package:' or 'file:' from )
std::string ExtractSchemePrefix(std::string url) {
  if (url.find(kPackageScheme) == 0u)
    return kPackageScheme;
  if (url.find(kFileScheme) == 0u)
    return kFileScheme;
  return std::string();
}

// Extract the path from a package: or file: url.
std::string ExtractPath(std::string url) {
  if (url.find(kPackageScheme) == 0u)
    return url.substr(kPackageSchemeLength);
  if (url.find(kFileScheme) == 0u)
    return url.substr(kFileSchemeLength);
  return url;
}

}  // namespace

FileLoader::FileLoader(int dirfd) : dirfd_(dirfd) {}

FileLoader::~FileLoader() {
  for (auto kernel_buffer : kernel_buffers_)
    free(kernel_buffer);

  if (dirfd_ >= 0)
    close(dirfd_);
}

std::string FileLoader::SanitizeURIEscapedCharacters(const std::string& str) {
  std::string result;
  result.reserve(str.size());
  for (std::string::size_type i = 0; i < str.size(); ++i) {
    if (str[i] == '%') {
      if (i > str.size() - 3 || !isxdigit(str[i + 1]) || !isxdigit(str[i + 2]))
        return "";
      const std::string hex = str.substr(i + 1, 2);
      const unsigned char c = strtoul(hex.c_str(), nullptr, 16);
      if (!c)
        return "";
      result += c;
      i += 2;
    } else {
      result += str[i];
    }
  }
  return result;
}

bool FileLoader::LoadPackagesMap(const std::string& packages) {
  packages_ = packages;
  std::string packages_source;
  if (!ReadFileToString(packages_, &packages_source)) {
    tonic::Log("error: Unable to load .packages file '%s'.", packages_.c_str());
    return false;
  }
  packages_map_.reset(new PackagesMap());
  std::string error;
  if (!packages_map_->Parse(packages_source, &error)) {
    tonic::Log("error: Unable to parse .packages file '%s'. %s",
               packages_.c_str(), error.c_str());
    return false;
  }
  return true;
}

std::string FileLoader::GetFilePathForPackageURL(std::string url) {
  if (!packages_map_)
    return std::string();
  TONIC_DCHECK(url.find(kPackageScheme) == 0u);
  url = url.substr(kPackageSchemeLength);

  size_t slash = url.find(FileLoader::kPathSeparator);
  if (slash == std::string::npos)
    return std::string();
  std::string package = url.substr(0, slash);
  std::string library_path = url.substr(slash + 1);
  std::string package_path = packages_map_->Resolve(package);
  if (package_path.empty())
    return std::string();
  if (package_path.find(FileLoader::kFileURLPrefix) == 0u)
    return SanitizePath(package_path.substr(FileLoader::kFileURLPrefixLength) +
                        library_path);
  return filesystem::GetDirectoryName(filesystem::AbsolutePath(packages_)) +
         FileLoader::kPathSeparator + package_path +
         FileLoader::kPathSeparator + library_path;
}

Dart_Handle FileLoader::HandleLibraryTag(Dart_LibraryTag tag,
                                         Dart_Handle library,
                                         Dart_Handle url) {
  TONIC_DCHECK(Dart_IsNull(library) || Dart_IsLibrary(library) ||
               Dart_IsString(library));
  TONIC_DCHECK(Dart_IsString(url));
  if (tag == Dart_kCanonicalizeUrl)
    return CanonicalizeURL(library, url);
  if (tag == Dart_kKernelTag)
    return Kernel(url);
  if (tag == Dart_kImportTag)
    return Import(url);
  return Dart_NewApiError("Unknown library tag.");
}

Dart_Handle FileLoader::CanonicalizeURL(Dart_Handle library, Dart_Handle url) {
  std::string string = StdStringFromDart(url);
  if (string.find(kDartScheme) == 0u)
    return url;
  if (string.find(kPackageScheme) == 0u)
    return StdStringToDart(SanitizePath(string));
  if (string.find(kFileScheme) == 0u)
    return StdStringToDart(SanitizePath(CanonicalizeFileURL(string)));

  std::string library_url = StdStringFromDart(Dart_LibraryUrl(library));
  std::string prefix = ExtractSchemePrefix(library_url);
  std::string base_path = ExtractPath(library_url);
  std::string simplified_path =
      filesystem::SimplifyPath(filesystem::GetDirectoryName(base_path) +
                               FileLoader::kPathSeparator + string);
  return StdStringToDart(SanitizePath(prefix + simplified_path));
}

std::string FileLoader::GetFilePathForURL(std::string url) {
  if (url.find(kPackageScheme) == 0u)
    return GetFilePathForPackageURL(std::move(url));
  if (url.find(kFileScheme) == 0u)
    return GetFilePathForFileURL(std::move(url));
  return url;
}

Dart_Handle FileLoader::FetchBytes(const std::string& url,
                                   uint8_t*& buffer,
                                   intptr_t& buffer_size) {
  buffer = nullptr;
  buffer_size = -1;

  std::string path = filesystem::SimplifyPath(GetFilePathForURL(url));
  if (path.empty()) {
    std::string error_message = "error: Unable to read '" + url + "'.";
    return Dart_NewUnhandledExceptionError(
        Dart_NewStringFromCString(error_message.c_str()));
  }
  std::string absolute_path = filesystem::GetAbsoluteFilePath(path);
  auto result = filesystem::ReadFileToBytes(absolute_path);
  if (result.first == nullptr) {
    std::string error_message =
        "error: Unable to read '" + absolute_path + "'.";
    return Dart_NewUnhandledExceptionError(
        Dart_NewStringFromCString(error_message.c_str()));
  }
  buffer = result.first;
  buffer_size = result.second;
  return Dart_True();
}

Dart_Handle FileLoader::Import(Dart_Handle url) {
  std::string url_string = StdStringFromDart(url);
  uint8_t* buffer = nullptr;
  intptr_t buffer_size = -1;
  Dart_Handle result = FetchBytes(url_string, buffer, buffer_size);
  if (Dart_IsError(result)) {
    return result;
  }
  // The embedder must keep the buffer alive until isolate shutdown.
  kernel_buffers_.push_back(buffer);
  return Dart_LoadLibraryFromKernel(buffer, buffer_size);
}

namespace {
void MallocFinalizer(void* isolate_callback_data,
                     Dart_WeakPersistentHandle handle,
                     void* peer) {
  free(peer);
}
}  // namespace

Dart_Handle FileLoader::Kernel(Dart_Handle url) {
  std::string url_string = StdStringFromDart(url);
  uint8_t* buffer = nullptr;
  intptr_t buffer_size = -1;
  Dart_Handle result = FetchBytes(url_string, buffer, buffer_size);
  if (Dart_IsError(result)) {
    return result;
  }
  result =
      Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffer, buffer_size);
  Dart_NewWeakPersistentHandle(result, buffer, buffer_size, MallocFinalizer);
  return result;
}

// This is invoked upon a reload request.
void FileLoader::SetPackagesUrl(Dart_Handle url) {
  if (url == Dart_Null()) {
    // No packages url specified.
    LoadPackagesMap(packages());
    return;
  }
  const std::string& packages_url = StdStringFromDart(url);
  LoadPackagesMap(packages_url);
}

std::string FileLoader::GetFilePathForFileURL(std::string url) {
  TONIC_DCHECK(url.find(FileLoader::kFileURLPrefix) == 0u);
  return SanitizePath(url.substr(FileLoader::kFileURLPrefixLength));
}

std::string FileLoader::GetFileURLForPath(const std::string& path) {
  return std::string(FileLoader::kFileURLPrefix) + path;
}

}  // namespace tonic
