#ifndef SRC_NODE_REALM_H_
#define SRC_NODE_REALM_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include <v8.h>
#include <unordered_map>
#include "cleanup_queue.h"
#include "env_properties.h"
#include "memory_tracker.h"
#include "node_snapshotable.h"

namespace node {

struct RealmSerializeInfo {
  std::vector<std::string> builtins;
  std::vector<PropInfo> persistent_values;
  std::vector<PropInfo> native_objects;

  SnapshotIndex context;
  friend std::ostream& operator<<(std::ostream& o, const RealmSerializeInfo& i);
};

using BindingDataStore =
    std::array<BaseObjectWeakPtr<BaseObject>,
               static_cast<size_t>(BindingDataType::kBindingDataTypeCount)>;

/**
 * node::Realm is a container for a set of JavaScript objects and functions
 * that associated with a particular global environment.
 *
 * An ECMAScript realm (https://tc39.es/ecma262/#sec-code-realms) representing
 * a global environment in which script is run. Each ECMAScript realm comes
 * with a global object and a set of intrinsic objects. An ECMAScript realm has
 * a [[HostDefined]] field, which contains the node::Realm object.
 *
 * Realm can be a principal realm or a synthetic realm. A principal realm is
 * created with an Environment as its principal global environment to evaluate
 * scripts. A synthetic realm is created with JS APIs like ShadowRealm.
 *
 * Native bindings and builtin modules can be evaluated in either a principal
 * realm or a synthetic realm.
 */
class Realm : public MemoryRetainer {
 public:
  enum Kind {
    kPrincipal,
    kShadowRealm,
  };

  static inline Realm* GetCurrent(v8::Isolate* isolate);
  static inline Realm* GetCurrent(v8::Local<v8::Context> context);
  static inline Realm* GetCurrent(
      const v8::FunctionCallbackInfo<v8::Value>& info);
  template <typename T>
  static inline Realm* GetCurrent(const v8::PropertyCallbackInfo<T>& info);

  Realm(Environment* env, v8::Local<v8::Context> context, Kind kind);

  Realm(const Realm&) = delete;
  Realm& operator=(const Realm&) = delete;
  Realm(Realm&&) = delete;
  Realm& operator=(Realm&&) = delete;

  void MemoryInfo(MemoryTracker* tracker) const override;

  void CreateProperties();
  RealmSerializeInfo Serialize(v8::SnapshotCreator* creator);
  void DeserializeProperties(const RealmSerializeInfo* info);

  v8::MaybeLocal<v8::Value> ExecuteBootstrapper(const char* id);
  v8::MaybeLocal<v8::Value> RunBootstrapping();

  inline void AddCleanupHook(CleanupQueue::Callback cb, void* arg);
  inline void RemoveCleanupHook(CleanupQueue::Callback cb, void* arg);
  inline bool HasCleanupHooks() const;
  void RunCleanup();

  template <typename T>
  void ForEachBaseObject(T&& iterator) const;

  void PrintInfoForSnapshot();
  void VerifyNoStrongBaseObjects();

  inline IsolateData* isolate_data() const;
  inline Environment* env() const;
  inline v8::Isolate* isolate() const;
  inline Kind kind() const;
  virtual v8::Local<v8::Context> context() const;
  inline bool has_run_bootstrapping_code() const;

  // Methods created using SetMethod(), SetPrototypeMethod(), etc. inside
  // this scope can access the created T* object using
  // GetBindingData<T>(args) later.
  template <typename T, typename... Args>
  T* AddBindingData(v8::Local<v8::Object> target, Args&&... args);
  template <typename T, typename U>
  static inline T* GetBindingData(const v8::PropertyCallbackInfo<U>& info);
  template <typename T>
  static inline T* GetBindingData(
      const v8::FunctionCallbackInfo<v8::Value>& info);
  template <typename T>
  static inline T* GetBindingData(v8::Local<v8::Context> context);
  template <typename T>
  inline T* GetBindingData();
  inline BindingDataStore* binding_data_store();

  // The BaseObject count is a debugging helper that makes sure that there are
  // no memory leaks caused by BaseObjects staying alive longer than expected
  // (in particular, no circular BaseObjectPtr references).
  inline void modify_base_object_count(int64_t delta);
  inline int64_t base_object_count() const;

  // Base object count created after the bootstrap of the realm.
  inline int64_t base_object_created_after_bootstrap() const;

#define V(PropertyName, TypeName)                                              \
  virtual v8::Local<TypeName> PropertyName() const = 0;                        \
  virtual void set_##PropertyName(v8::Local<TypeName> value) = 0;
  PER_REALM_STRONG_PERSISTENT_VALUES(V)
#undef V

  std::set<struct node_module*> internal_bindings;
  std::set<std::string> builtins_with_cache;
  std::set<std::string> builtins_without_cache;
  // This is only filled during deserialization. We use a vector since
  // it's only used for tests.
  std::vector<std::string> builtins_in_snapshot;

 protected:
  ~Realm();

  virtual v8::MaybeLocal<v8::Value> BootstrapRealm() = 0;

  Environment* env_;
  // Shorthand for isolate pointer.
  v8::Isolate* isolate_;
  v8::Global<v8::Context> context_;

#define V(PropertyName, TypeName) v8::Global<TypeName> PropertyName##_;
  PER_REALM_STRONG_PERSISTENT_VALUES(V)
#undef V

 private:
  void InitializeContext(v8::Local<v8::Context> context,
                         const RealmSerializeInfo* realm_info);
  void DoneBootstrapping();

  Kind kind_;
  bool has_run_bootstrapping_code_ = false;

  int64_t base_object_count_ = 0;
  int64_t base_object_created_by_bootstrap_ = 0;

  BindingDataStore binding_data_store_;

  CleanupQueue cleanup_queue_;
};

class PrincipalRealm : public Realm {
 public:
  PrincipalRealm(Environment* env,
                 v8::Local<v8::Context> context,
                 const RealmSerializeInfo* realm_info);
  ~PrincipalRealm();

  SET_MEMORY_INFO_NAME(PrincipalRealm)
  SET_SELF_SIZE(PrincipalRealm)

#define V(PropertyName, TypeName)                                              \
  v8::Local<TypeName> PropertyName() const override;                           \
  void set_##PropertyName(v8::Local<TypeName> value) override;
  PER_REALM_STRONG_PERSISTENT_VALUES(V)
#undef V

 protected:
  v8::MaybeLocal<v8::Value> BootstrapRealm() override;
};

}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#endif  // SRC_NODE_REALM_H_
