// Copyright 2014 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

// CFXJS_ENGINE is a layer that makes it easier to define native objects in V8,
// but has no knowledge of PDF-specific native objects. It could in theory be
// used to implement other sets of native objects.

// PDFium code should include this file rather than including V8 headers
// directly.

#ifndef FXJS_CFXJS_ENGINE_H_
#define FXJS_CFXJS_ENGINE_H_

#include <functional>
#include <map>
#include <memory>
#include <utility>
#include <vector>

#include "core/fxcrt/widestring.h"
#include "fxjs/cfx_v8.h"
#include "fxjs/ijs_runtime.h"
#include "v8/include/v8-forward.h"
#include "v8/include/v8-function-callback.h"
#include "v8/include/v8-persistent-handle.h"
#include "v8/include/v8-template.h"

class CFXJS_ObjDefinition;
class V8TemplateMap;

enum FXJSOBJTYPE {
  FXJSOBJTYPE_DYNAMIC = 0,  // Created by native method and returned to JS.
  FXJSOBJTYPE_STATIC,       // Created by init and hung off of global object.
  FXJSOBJTYPE_GLOBAL,       // The global object itself (may only appear once).
};

class CFXJS_PerIsolateData {
 public:
  // Hook for XFA's data, when present.
  class ExtensionIface {
   public:
    virtual ~ExtensionIface() = default;
  };

  ~CFXJS_PerIsolateData();

  static void SetUp(v8::Isolate* pIsolate);
  static CFXJS_PerIsolateData* Get(v8::Isolate* pIsolate);

  uint32_t CurrentMaxObjDefinitionID() const;
  CFXJS_ObjDefinition* ObjDefinitionForID(uint32_t id) const;
  uint32_t AssignIDForObjDefinition(std::unique_ptr<CFXJS_ObjDefinition> pDefn);
  V8TemplateMap* GetDynamicObjsMap() { return dynamic_objs_map_.get(); }
  ExtensionIface* GetExtension() { return extension_.get(); }
  void SetExtension(std::unique_ptr<ExtensionIface> extension) {
    extension_ = std::move(extension);
  }

 private:
  explicit CFXJS_PerIsolateData(v8::Isolate* pIsolate);

  const wchar_t* const tag_;  // Raw, always a literal.
  std::vector<std::unique_ptr<CFXJS_ObjDefinition>> object_defn_array_;
  std::unique_ptr<V8TemplateMap> dynamic_objs_map_;
  std::unique_ptr<ExtensionIface> extension_;
};

class CFXJS_PerObjectData {
 public:
  // Object on the C++ side to which the v8::Object is bound.
  class Binding {
   public:
    virtual ~Binding() = default;
  };

  static void SetNewDataInObject(FXJSOBJTYPE eObjType,
                                 uint32_t nObjDefnID,
                                 v8::Local<v8::Object> pObj);
  static CFXJS_PerObjectData* GetFromObject(v8::Local<v8::Object> pObj);

  ~CFXJS_PerObjectData();

  uint32_t GetObjDefnID() const { return obj_defn_id_; }
  Binding* GetBinding() { return binding_.get(); }
  void SetBinding(std::unique_ptr<Binding> p) { binding_ = std::move(p); }

 private:
  CFXJS_PerObjectData(FXJSOBJTYPE eObjType, uint32_t nObjDefnID);

  static bool HasInternalFields(v8::Local<v8::Object> pObj);
  static CFXJS_PerObjectData* ExtractFromObject(v8::Local<v8::Object> pObj);

  const FXJSOBJTYPE obj_type_;
  const uint32_t obj_defn_id_;
  std::unique_ptr<Binding> binding_;
};

void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate);
void FXJS_Release();

// Gets the global isolate set by FXJS_Initialize(), or makes a new one each
// time if there is no such isolate. Returns true if a new isolate had to be
// created.
bool FXJS_GetIsolate(v8::Isolate** pResultIsolate);

// Get the global isolate's ref count.
size_t FXJS_GlobalIsolateRefCount();

class CFXJS_Engine : public CFX_V8 {
 public:
  explicit CFXJS_Engine(v8::Isolate* pIsolate);
  ~CFXJS_Engine() override;

  using Constructor = std::function<void(CFXJS_Engine* pEngine,
                                         v8::Local<v8::Object> obj,
                                         v8::Local<v8::Object> proxy)>;
  using Destructor = std::function<void(v8::Local<v8::Object> obj)>;

  static uint32_t GetObjDefnID(v8::Local<v8::Object> pObj);
  static CFXJS_PerObjectData::Binding* GetBinding(v8::Isolate* pIsolate,
                                                  v8::Local<v8::Object> pObj);
  static void SetBinding(v8::Local<v8::Object> pObj,
                         std::unique_ptr<CFXJS_PerObjectData::Binding> p);
  static void FreePerObjectData(v8::Local<v8::Object> pObj);

  // Always returns a valid (i.e. non-zero), newly-created objDefnID.
  uint32_t DefineObj(const char* sObjName,
                     FXJSOBJTYPE eObjType,
                     Constructor pConstructor,
                     Destructor pDestructor);

  void DefineObjMethod(uint32_t nObjDefnID,
                       const char* sMethodName,
                       v8::FunctionCallback pMethodCall);
  void DefineObjProperty(uint32_t nObjDefnID,
                         const char* sPropName,
                         v8::AccessorNameGetterCallback pPropGet,
                         v8::AccessorNameSetterCallback pPropPut);
  void DefineObjAllProperties(uint32_t nObjDefnID,
                              v8::NamedPropertyQueryCallback pPropQurey,
                              v8::NamedPropertyGetterCallback pPropGet,
                              v8::NamedPropertySetterCallback pPropPut,
                              v8::NamedPropertyDeleterCallback pPropDel,
                              v8::NamedPropertyEnumeratorCallback pPropEnum);
  void DefineObjConst(uint32_t nObjDefnID,
                      const char* sConstName,
                      v8::Local<v8::Value> pDefault);
  void DefineGlobalMethod(const char* sMethodName,
                          v8::FunctionCallback pMethodCall);
  void DefineGlobalConst(const wchar_t* sConstName,
                         v8::FunctionCallback pConstGetter);

  // Called after FXJS_Define* calls made.
  void InitializeEngine();
  void ReleaseEngine();

  // Called after FXJS_InitializeEngine call made.
  std::optional<IJS_Runtime::JS_Error> Execute(const WideString& script);

  v8::Local<v8::Object> GetThisObj();
  v8::Local<v8::Object> NewFXJSBoundObject(uint32_t nObjDefnID,
                                           FXJSOBJTYPE type);
  void Error(const WideString& message);

  v8::Local<v8::Context> GetV8Context();

  v8::Local<v8::Array> GetConstArray(const WideString& name);
  void SetConstArray(const WideString& name, v8::Local<v8::Array> array);

 protected:
  CFXJS_Engine();

 private:
  v8::Global<v8::Context> v8_context_;
  std::vector<v8::Global<v8::Object>> static_objects_;
  std::map<WideString, v8::Global<v8::Array>> const_arrays_;
};

#endif  // FXJS_CFXJS_ENGINE_H_
