#ifndef SRC_NODE_BLOB_H_
#define SRC_NODE_BLOB_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "async_wrap.h"
#include "base_object.h"
#include "env.h"
#include "memory_tracker.h"
#include "node_internals.h"
#include "node_snapshotable.h"
#include "node_worker.h"
#include "v8.h"

#include <string>
#include <unordered_map>
#include <vector>

namespace node {

struct BlobEntry {
  std::shared_ptr<v8::BackingStore> store;
  size_t length;
  size_t offset;
};

class Blob : public BaseObject {
 public:
  static void RegisterExternalReferences(
      ExternalReferenceRegistry* registry);

  static void Initialize(
      v8::Local<v8::Object> target,
      v8::Local<v8::Value> unused,
      v8::Local<v8::Context> context,
      void* priv);

  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void ToArrayBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void ToSlice(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void RevokeDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);

  static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
      Environment* env);

  static BaseObjectPtr<Blob> Create(Environment* env,
                                    const std::vector<BlobEntry>& store,
                                    size_t length);

  static bool HasInstance(Environment* env, v8::Local<v8::Value> object);

  const std::vector<BlobEntry>& entries() const { return store_; }

  void MemoryInfo(MemoryTracker* tracker) const override;
  SET_MEMORY_INFO_NAME(Blob)
  SET_SELF_SIZE(Blob)

  // Copies the contents of the Blob into an ArrayBuffer.
  v8::MaybeLocal<v8::Value> GetArrayBuffer(Environment* env);

  BaseObjectPtr<Blob> Slice(Environment* env, size_t start, size_t end);

  inline size_t length() const { return length_; }

  class BlobTransferData : public worker::TransferData {
   public:
    explicit BlobTransferData(
        const std::vector<BlobEntry>& store,
      size_t length)
        : store_(store),
          length_(length) {}

    BaseObjectPtr<BaseObject> Deserialize(
        Environment* env,
        v8::Local<v8::Context> context,
        std::unique_ptr<worker::TransferData> self) override;

    SET_MEMORY_INFO_NAME(BlobTransferData)
    SET_SELF_SIZE(BlobTransferData)
    SET_NO_MEMORY_INFO()

   private:
    std::vector<BlobEntry> store_;
    size_t length_ = 0;
  };

  BaseObject::TransferMode GetTransferMode() const override;
  std::unique_ptr<worker::TransferData> CloneForMessaging() const override;

  Blob(
      Environment* env,
      v8::Local<v8::Object> obj,
      const std::vector<BlobEntry>& store,
      size_t length);

 private:
  std::vector<BlobEntry> store_;
  size_t length_ = 0;
};

class FixedSizeBlobCopyJob : public AsyncWrap, public ThreadPoolWork {
 public:
  enum class Mode {
    SYNC,
    ASYNC
  };

  static void RegisterExternalReferences(
      ExternalReferenceRegistry* registry);
  static void Initialize(Environment* env, v8::Local<v8::Object> target);
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void Run(const v8::FunctionCallbackInfo<v8::Value>& args);

  bool IsNotIndicativeOfMemoryLeakAtExit() const override {
    return true;
  }

  void DoThreadPoolWork() override;
  void AfterThreadPoolWork(int status) override;

  Mode mode() const { return mode_; }

  void MemoryInfo(MemoryTracker* tracker) const override;
  SET_MEMORY_INFO_NAME(FixedSizeBlobCopyJob)
  SET_SELF_SIZE(FixedSizeBlobCopyJob)

 private:
  FixedSizeBlobCopyJob(
    Environment* env,
    v8::Local<v8::Object> object,
    Blob* blob,
    Mode mode = Mode::ASYNC);

  Mode mode_;
  std::vector<BlobEntry> source_;
  std::shared_ptr<v8::BackingStore> destination_;
  size_t length_ = 0;
};

class BlobBindingData : public SnapshotableObject {
 public:
  explicit BlobBindingData(Environment* env, v8::Local<v8::Object> wrap);

  using InternalFieldInfo = InternalFieldInfoBase;

  SERIALIZABLE_OBJECT_METHODS()

  static constexpr FastStringKey type_name{"node::BlobBindingData"};
  static constexpr EmbedderObjectType type_int =
      EmbedderObjectType::k_blob_binding_data;

  void MemoryInfo(MemoryTracker* tracker) const override;
  SET_SELF_SIZE(BlobBindingData)
  SET_MEMORY_INFO_NAME(BlobBindingData)

  struct StoredDataObject : public MemoryRetainer {
    BaseObjectPtr<Blob> blob;
    size_t length;
    std::string type;

    StoredDataObject() = default;

    StoredDataObject(
        const BaseObjectPtr<Blob>& blob_,
        size_t length_,
        const std::string& type_);

    void MemoryInfo(MemoryTracker* tracker) const override;
    SET_SELF_SIZE(StoredDataObject)
    SET_MEMORY_INFO_NAME(StoredDataObject)
  };

  void store_data_object(
      const std::string& uuid,
      const StoredDataObject& object);

  void revoke_data_object(const std::string& uuid);

  StoredDataObject get_data_object(const std::string& uuid);

 private:
  std::unordered_map<std::string, StoredDataObject> data_objects_;
};

}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#endif  // SRC_NODE_BLOB_H_
