// Copyright 2013 The Flutter 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 "flutter/runtime/isolate_configuration.h"

#include "flutter/fml/make_copyable.h"
#include "flutter/runtime/dart_vm.h"

namespace flutter {

IsolateConfiguration::IsolateConfiguration() = default;

IsolateConfiguration::~IsolateConfiguration() = default;

bool IsolateConfiguration::PrepareIsolate(DartIsolate& isolate) {
  if (isolate.GetPhase() != DartIsolate::Phase::LibrariesSetup) {
    FML_DLOG(ERROR)
        << "Isolate was in incorrect phase to be prepared for running.";
    return false;
  }

  return DoPrepareIsolate(isolate);
}

class AppSnapshotIsolateConfiguration final : public IsolateConfiguration {
 public:
  AppSnapshotIsolateConfiguration() = default;

  // |IsolateConfiguration|
  bool DoPrepareIsolate(DartIsolate& isolate) override {
    return isolate.PrepareForRunningFromPrecompiledCode();
  }

  // |IsolateConfiguration|
  bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override {
    return snapshot.IsNullSafetyEnabled(nullptr);
  }

 private:
  FML_DISALLOW_COPY_AND_ASSIGN(AppSnapshotIsolateConfiguration);
};

class KernelIsolateConfiguration : public IsolateConfiguration {
 public:
  explicit KernelIsolateConfiguration(
      std::unique_ptr<const fml::Mapping> kernel)
      : kernel_(std::move(kernel)) {}

  // |IsolateConfiguration|
  bool DoPrepareIsolate(DartIsolate& isolate) override {
    if (DartVM::IsRunningPrecompiledCode()) {
      return false;
    }
    return isolate.PrepareForRunningFromKernel(std::move(kernel_),
                                               /*child_isolate=*/false,
                                               /*last_piece=*/true);
  }

  // |IsolateConfiguration|
  bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override {
    return snapshot.IsNullSafetyEnabled(kernel_.get());
  }

 private:
  std::unique_ptr<const fml::Mapping> kernel_;

  FML_DISALLOW_COPY_AND_ASSIGN(KernelIsolateConfiguration);
};

class KernelListIsolateConfiguration final : public IsolateConfiguration {
 public:
  explicit KernelListIsolateConfiguration(
      std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
          kernel_pieces)
      : kernel_piece_futures_(std::move(kernel_pieces)) {
    if (kernel_piece_futures_.empty()) {
      FML_LOG(ERROR) << "Attempted to create kernel list configuration without "
                        "any kernel blobs.";
    }
  }

  // |IsolateConfiguration|
  bool DoPrepareIsolate(DartIsolate& isolate) override {
    if (DartVM::IsRunningPrecompiledCode()) {
      return false;
    }

    ResolveKernelPiecesIfNecessary();

    if (resolved_kernel_pieces_.empty()) {
      FML_DLOG(ERROR) << "No kernel pieces provided to prepare this isolate.";
      return false;
    }

    for (size_t i = 0; i < resolved_kernel_pieces_.size(); i++) {
      if (!resolved_kernel_pieces_[i]) {
        FML_DLOG(ERROR) << "This kernel list isolate configuration was already "
                           "used to prepare an isolate.";
        return false;
      }
      const bool last_piece = i + 1 == resolved_kernel_pieces_.size();
      if (!isolate.PrepareForRunningFromKernel(
              std::move(resolved_kernel_pieces_[i]), /*child_isolate=*/false,
              last_piece)) {
        return false;
      }
    }

    return true;
  }

  // |IsolateConfiguration|
  bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override {
    ResolveKernelPiecesIfNecessary();
    const auto kernel = resolved_kernel_pieces_.empty()
                            ? nullptr
                            : resolved_kernel_pieces_.front().get();
    return snapshot.IsNullSafetyEnabled(kernel);
  }

  // This must be call as late as possible before accessing any of the kernel
  // pieces. This will delay blocking on the futures for as long as possible. So
  // far, only Fuchsia depends on this optimization and only on the non-AOT
  // configs.
  void ResolveKernelPiecesIfNecessary() {
    if (resolved_kernel_pieces_.size() == kernel_piece_futures_.size()) {
      return;
    }

    resolved_kernel_pieces_.clear();
    for (auto& piece : kernel_piece_futures_) {
      // The get() call will xfer the unique pointer out and leave an empty
      // future in the original vector.
      resolved_kernel_pieces_.emplace_back(piece.get());
    }
  }

 private:
  std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
      kernel_piece_futures_;
  std::vector<std::unique_ptr<const fml::Mapping>> resolved_kernel_pieces_;

  FML_DISALLOW_COPY_AND_ASSIGN(KernelListIsolateConfiguration);
};

static std::vector<std::string> ParseKernelListPaths(
    std::unique_ptr<fml::Mapping> kernel_list) {
  FML_DCHECK(kernel_list);

  std::vector<std::string> kernel_pieces_paths;

  const char* kernel_list_str =
      reinterpret_cast<const char*>(kernel_list->GetMapping());
  size_t kernel_list_size = kernel_list->GetSize();

  size_t piece_path_start = 0;
  while (piece_path_start < kernel_list_size) {
    size_t piece_path_end = piece_path_start;
    while ((piece_path_end < kernel_list_size) &&
           (kernel_list_str[piece_path_end] != '\n')) {
      piece_path_end++;
    }
    std::string piece_path(&kernel_list_str[piece_path_start],
                           piece_path_end - piece_path_start);
    kernel_pieces_paths.emplace_back(std::move(piece_path));

    piece_path_start = piece_path_end + 1;
  }

  return kernel_pieces_paths;
}

static std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
PrepareKernelMappings(const std::vector<std::string>& kernel_pieces_paths,
                      const std::shared_ptr<AssetManager>& asset_manager,
                      const fml::RefPtr<fml::TaskRunner>& io_worker) {
  FML_DCHECK(asset_manager);
  std::vector<std::future<std::unique_ptr<const fml::Mapping>>> fetch_futures;

  for (const auto& kernel_pieces_path : kernel_pieces_paths) {
    std::promise<std::unique_ptr<const fml::Mapping>> fetch_promise;
    fetch_futures.push_back(fetch_promise.get_future());
    auto fetch_task =
        fml::MakeCopyable([asset_manager, kernel_pieces_path,
                           fetch_promise = std::move(fetch_promise)]() mutable {
          fetch_promise.set_value(
              asset_manager->GetAsMapping(kernel_pieces_path));
        });
    // Fulfill the promise on the worker if one is available or the current
    // thread if one is not.
    if (io_worker) {
      io_worker->PostTask(fetch_task);
    } else {
      fetch_task();
    }
  }

  return fetch_futures;
}

std::unique_ptr<IsolateConfiguration> IsolateConfiguration::InferFromSettings(
    const Settings& settings,
    const std::shared_ptr<AssetManager>& asset_manager,
    const fml::RefPtr<fml::TaskRunner>& io_worker) {
  // Running in AOT mode.
  if (DartVM::IsRunningPrecompiledCode()) {
    return CreateForAppSnapshot();
  }

  if (settings.application_kernels) {
    return CreateForKernelList(settings.application_kernels());
  }

  if (settings.application_kernel_asset.empty() &&
      settings.application_kernel_list_asset.empty()) {
    FML_DLOG(ERROR) << "application_kernel_asset or "
                       "application_kernel_list_asset must be set";
    return nullptr;
  }

  if (!asset_manager) {
    FML_DLOG(ERROR) << "No asset manager specified when attempting to create "
                       "isolate configuration.";
    return nullptr;
  }

  // Running from kernel snapshot. Requires asset manager.
  {
    std::unique_ptr<fml::Mapping> kernel =
        asset_manager->GetAsMapping(settings.application_kernel_asset);
    if (kernel) {
      return CreateForKernel(std::move(kernel));
    }
  }

  // Running from kernel divided into several pieces (for sharing). Requires
  // asset manager and io worker.

  if (!io_worker) {
    FML_DLOG(ERROR) << "No IO worker specified to load kernel pieces.";
    return nullptr;
  }

  {
    std::unique_ptr<fml::Mapping> kernel_list =
        asset_manager->GetAsMapping(settings.application_kernel_list_asset);
    if (!kernel_list) {
      FML_LOG(ERROR) << "Failed to load: "
                     << settings.application_kernel_list_asset;
      return nullptr;
    }
    auto kernel_pieces_paths = ParseKernelListPaths(std::move(kernel_list));
    auto kernel_mappings =
        PrepareKernelMappings(kernel_pieces_paths, asset_manager, io_worker);
    return CreateForKernelList(std::move(kernel_mappings));
  }

  return nullptr;
}

std::unique_ptr<IsolateConfiguration>
IsolateConfiguration::CreateForAppSnapshot() {
  return std::make_unique<AppSnapshotIsolateConfiguration>();
}

std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernel(
    std::unique_ptr<const fml::Mapping> kernel) {
  return std::make_unique<KernelIsolateConfiguration>(std::move(kernel));
}

std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernelList(
    std::vector<std::unique_ptr<const fml::Mapping>> kernel_pieces) {
  std::vector<std::future<std::unique_ptr<const fml::Mapping>>> pieces;
  for (auto& piece : kernel_pieces) {
    if (!piece) {
      FML_DLOG(ERROR) << "Invalid kernel piece.";
      continue;
    }
    std::promise<std::unique_ptr<const fml::Mapping>> promise;
    pieces.push_back(promise.get_future());
    promise.set_value(std::move(piece));
  }
  return CreateForKernelList(std::move(pieces));
}

std::unique_ptr<IsolateConfiguration> IsolateConfiguration::CreateForKernelList(
    std::vector<std::future<std::unique_ptr<const fml::Mapping>>>
        kernel_pieces) {
  return std::make_unique<KernelListIsolateConfiguration>(
      std::move(kernel_pieces));
}

}  // namespace flutter
