// 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.

#ifndef RUNTIME_BIN_ISOLATE_DATA_H_
#define RUNTIME_BIN_ISOLATE_DATA_H_

#include <memory>
#include <utility>

#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/globals.h"

namespace dart {

// Forward declaration.
template <typename T>
class MallocGrowableArray;

}  // namespace dart

namespace dart {
namespace bin {

// Forward declaration.
class AppSnapshot;
class EventHandler;
class Loader;

// Data associated with every isolate group in the standalone VM
// embedding. This is used to free external resources for each isolate
// group when the isolate group shuts down.
class IsolateGroupData {
 public:
  IsolateGroupData(const char* url,
                   const char* package_root,
                   const char* packages_file,
                   AppSnapshot* app_snapshot,
                   bool isolate_run_app_snapshot);
  ~IsolateGroupData();

  char* script_url;
  char* package_root;

  const std::shared_ptr<uint8_t>& kernel_buffer() const {
    return kernel_buffer_;
  }

  intptr_t kernel_buffer_size() const { return kernel_buffer_size_; }

  // Associate the given kernel buffer with this IsolateGroupData without
  // giving it ownership of the buffer.
  void SetKernelBufferUnowned(uint8_t* buffer, intptr_t size) {
    ASSERT(kernel_buffer_.get() == NULL);
    kernel_buffer_ = std::shared_ptr<uint8_t>(buffer, FreeUnownedKernelBuffer);
    kernel_buffer_size_ = size;
  }

  // Associate the given kernel buffer with this IsolateGroupData and give it
  // ownership of the buffer. This IsolateGroupData is the first one to own the
  // buffer.
  void SetKernelBufferNewlyOwned(uint8_t* buffer, intptr_t size) {
    ASSERT(kernel_buffer_.get() == NULL);
    kernel_buffer_ = std::shared_ptr<uint8_t>(buffer, free);
    kernel_buffer_size_ = size;
  }

  // Associate the given kernel buffer with this IsolateGroupData and give it
  // ownership of the buffer. The buffer is already owned by another
  // IsolateGroupData.
  void SetKernelBufferAlreadyOwned(std::shared_ptr<uint8_t> buffer,
                                   intptr_t size) {
    ASSERT(kernel_buffer_.get() == NULL);
    kernel_buffer_ = std::move(buffer);
    kernel_buffer_size_ = size;
  }

  const char* resolved_packages_config() const {
    return resolved_packages_config_;
  }

  void set_resolved_packages_config(const char* packages_config) {
    if (resolved_packages_config_ != NULL) {
      free(resolved_packages_config_);
      resolved_packages_config_ = NULL;
    }
    resolved_packages_config_ = strdup(packages_config);
  }

  MallocGrowableArray<char*>* dependencies() const { return dependencies_; }
  void set_dependencies(MallocGrowableArray<char*>* deps) {
    dependencies_ = deps;
  }

  bool RunFromAppSnapshot() const {
    // If the main isolate is using an app snapshot the [app_snapshot_] pointer
    // will be still nullptr (see main.cc:CreateIsolateGroupAndSetupHelper)
    //
    // Because of thus we have an additional boolean signaling whether the
    // isolate was started from an app snapshot.
    return app_snapshot_ != nullptr || isolate_run_app_snapshot_;
  }

 private:
  friend class IsolateData;  // For packages_file_

  std::unique_ptr<AppSnapshot> app_snapshot_;
  MallocGrowableArray<char*>* dependencies_;
  char* resolved_packages_config_;
  std::shared_ptr<uint8_t> kernel_buffer_;
  intptr_t kernel_buffer_size_;
  char* packages_file_ = nullptr;
  bool isolate_run_app_snapshot_;

  static void FreeUnownedKernelBuffer(uint8_t*) {}

  DISALLOW_COPY_AND_ASSIGN(IsolateGroupData);
};

// Data associated with every isolate in the standalone VM
// embedding. This is used to free external resources for each isolate
// when the isolate shuts down.
class IsolateData {
 public:
  explicit IsolateData(IsolateGroupData* isolate_group_data);
  ~IsolateData();

  IsolateGroupData* isolate_group_data() const { return isolate_group_data_; }

  void UpdatePackagesFile(const char* packages_file) {
    if (packages_file != nullptr) {
      free(packages_file_);
      packages_file_ = nullptr;
    }
    packages_file_ = strdup(packages_file);
  }

  // While loading a loader is associated with the isolate.
  bool HasLoader() const { return loader_ != NULL; }
  Loader* loader() const {
    ASSERT(loader_ != NULL);
    return loader_;
  }
  void set_loader(Loader* loader) {
    ASSERT((loader_ == NULL) || (loader == NULL));
    loader_ = loader;
  }

  const char* packages_file() const { return packages_file_; }

 private:
  IsolateGroupData* isolate_group_data_;
  Loader* loader_;
  char* packages_file_;

  DISALLOW_COPY_AND_ASSIGN(IsolateData);
};

}  // namespace bin
}  // namespace dart

#endif  // RUNTIME_BIN_ISOLATE_DATA_H_
