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

#ifndef FXJS_XFA_CFXJSE_ENGINE_H_
#define FXJS_XFA_CFXJSE_ENGINE_H_

#include <map>
#include <memory>
#include <type_traits>
#include <vector>

#include "core/fxcrt/mask.h"
#include "core/fxcrt/unowned_ptr.h"
#include "fxjs/cfx_v8.h"
#include "v8/include/cppgc/persistent.h"
#include "v8/include/v8-forward.h"
#include "v8/include/v8-persistent-handle.h"
#include "xfa/fxfa/cxfa_eventparam.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_script.h"
#include "xfa/fxfa/parser/xfa_basic_data.h"

class CFXJSE_Class;
class CFXJSE_Context;
class CFXJSE_FormCalcContext;
class CFXJSE_HostObject;
class CFXJSE_NodeHelper;
class CFXJSE_ResolveProcessor;
class CFXJSE_Value;
class CJS_Runtime;

enum class XFA_ResolveFlag : uint16_t {
  kChildren = 1 << 0,
  kTagName = 1 << 1,
  kAttributes = 1 << 2,
  kProperties = 1 << 3,
  kSiblings = 1 << 5,
  kParent = 1 << 6,
  kAnyChild = 1 << 7,
  kALL = 1 << 8,
  kCreateNode = 1 << 10,
  kBind = 1 << 11,
  kBindNew = 1 << 12,
};

class CFXJSE_Engine final : public CFX_V8 {
 public:
  class ResolveResult {
    CPPGC_STACK_ALLOCATED();  // Allow raw/unowned pointers.

   public:
    enum class Type {
      kNodes = 0,
      kAttribute,
      kCreateNodeOne,
      kCreateNodeAll,
      kCreateNodeMidAll,
      kExistNodes,
    };

    ResolveResult();
    ResolveResult(const ResolveResult& that);
    ResolveResult& operator=(const ResolveResult& that);
    ~ResolveResult();

    Type type = Type::kNodes;
    XFA_SCRIPTATTRIBUTEINFO script_attribute = {};

    // Vector of Member would be correct for stack-based vectors, if
    // STL worked with cppgc.
    std::vector<cppgc::Member<CXFA_Object>> objects;
  };

  static CXFA_Object* ToObject(const v8::FunctionCallbackInfo<v8::Value>& info);
  static CXFA_Object* ToObject(v8::Isolate* pIsolate,
                               v8::Local<v8::Value> value);
  static CXFA_Object* ToObject(v8::Isolate* pIsolate, CFXJSE_Value* pValue);
  static CXFA_Object* ToObject(CFXJSE_HostObject* pHostObj);
  static v8::Local<v8::Value> GlobalPropertyGetter(
      v8::Isolate* pIsolate,
      v8::Local<v8::Object> pObject,
      ByteStringView szPropName);
  static void GlobalPropertySetter(v8::Isolate* pIsolate,
                                   v8::Local<v8::Object> pObject,
                                   ByteStringView szPropName,
                                   v8::Local<v8::Value> pValue);
  static v8::Local<v8::Value> NormalPropertyGetter(
      v8::Isolate* pIsolate,
      v8::Local<v8::Object> pObject,
      ByteStringView szPropName);
  static void NormalPropertySetter(v8::Isolate* pIsolate,
                                   v8::Local<v8::Object> pObject,
                                   ByteStringView szPropName,
                                   v8::Local<v8::Value> pValue);
  static CJS_Result NormalMethodCall(
      const v8::FunctionCallbackInfo<v8::Value>& info,
      const WideString& functionName);
  static FXJSE_ClassPropType NormalPropTypeGetter(v8::Isolate* pIsolate,
                                                  v8::Local<v8::Object> pObject,
                                                  ByteStringView szPropName,
                                                  bool bQueryIn);
  static FXJSE_ClassPropType GlobalPropTypeGetter(v8::Isolate* pIsolate,
                                                  v8::Local<v8::Object> pObject,
                                                  ByteStringView szPropName,
                                                  bool bQueryIn);

  CFXJSE_Engine(CXFA_Document* pDocument, CJS_Runtime* fxjs_runtime);
  ~CFXJSE_Engine() override;

  void SetEventParam(CXFA_EventParam* param) { m_eventParam = param; }
  CXFA_EventParam* GetEventParam() const { return m_eventParam; }
  bool RunScript(CXFA_Script::Type eScriptType,
                 WideStringView wsScript,
                 CFXJSE_Value* pRetValue,
                 CXFA_Object* pThisObject);

  absl::optional<ResolveResult> ResolveObjects(CXFA_Object* refObject,
                                               WideStringView wsExpression,
                                               Mask<XFA_ResolveFlag> dwStyles);

  absl::optional<ResolveResult> ResolveObjectsWithBindNode(
      CXFA_Object* refObject,
      WideStringView wsExpression,
      Mask<XFA_ResolveFlag> dwStyles,
      CXFA_Node* bindNode);

  v8::Local<v8::Object> GetOrCreateJSBindingFromMap(CXFA_Object* pObject);

  CXFA_Object* GetThisObject() const { return m_pThisObject; }
  CFXJSE_Class* GetJseNormalClass() const { return m_pJsClass; }
  CXFA_Document* GetDocument() const { return m_pDocument.Get(); }

  void SetNodesOfRunScript(std::vector<cppgc::Persistent<CXFA_Node>>* pArray);
  void AddNodesOfRunScript(CXFA_Node* pNode);

  void SetRunAtType(XFA_AttributeValue eRunAt) { m_eRunAtType = eRunAt; }
  bool IsRunAtClient() { return m_eRunAtType != XFA_AttributeValue::Server; }

  CXFA_Script::Type GetType();

  void AddObjectToUpArray(CXFA_Node* pNode);
  CXFA_Node* LastObjectFromUpArray();

  CXFA_Object* ToXFAObject(v8::Local<v8::Value> obj);
  v8::Local<v8::Object> NewNormalXFAObject(CXFA_Object* obj);

  bool IsResolvingNodes() const { return m_bResolvingNodes; }

  CFXJSE_Context* GetJseContextForTest() const { return GetJseContext(); }

 private:
  CFXJSE_Context* GetJseContext() const { return m_JsContext.get(); }
  CFXJSE_Context* CreateVariablesContext(CXFA_Script* pScriptNode,
                                         CXFA_Node* pSubform);
  void RemoveBuiltInObjs(CFXJSE_Context* pContext);
  bool QueryNodeByFlag(CXFA_Node* refNode,
                       WideStringView propname,
                       v8::Local<v8::Value>* pValue,
                       Mask<XFA_ResolveFlag> dwFlag);
  bool UpdateNodeByFlag(CXFA_Node* refNode,
                        WideStringView propname,
                        v8::Local<v8::Value> pValue,
                        Mask<XFA_ResolveFlag> dwFlag);
  bool IsStrictScopeInJavaScript();
  CXFA_Object* GetVariablesThis(CXFA_Object* pObject);
  CXFA_Object* GetVariablesScript(CXFA_Object* pObject);
  CFXJSE_Context* VariablesContextForScriptNode(CXFA_Script* pScriptNode);
  bool QueryVariableValue(CXFA_Script* pScriptNode,
                          ByteStringView szPropName,
                          v8::Local<v8::Value>* pValue);
  bool UpdateVariableValue(CXFA_Script* pScriptNode,
                           ByteStringView szPropName,
                           v8::Local<v8::Value> pValue);
  void RunVariablesScript(CXFA_Script* pScriptNode);

  UnownedPtr<CJS_Runtime> const m_pSubordinateRuntime;
  cppgc::WeakPersistent<CXFA_Document> const m_pDocument;
  std::unique_ptr<CFXJSE_Context> m_JsContext;
  UnownedPtr<CFXJSE_Class> m_pJsClass;
  CXFA_Script::Type m_eScriptType = CXFA_Script::Type::Unknown;
  // |m_mapObjectToValue| is what ensures the v8 object bound to a
  // CJX_Object remains valid for the lifetime of the engine.
  std::map<CJX_Object*, v8::Global<v8::Object>> m_mapObjectToObject;
  std::map<CJX_Object*, std::unique_ptr<CFXJSE_Context>> m_mapVariableToContext;
  UnownedPtr<CXFA_EventParam> m_eventParam;
  std::vector<cppgc::Persistent<CXFA_Node>> m_upObjectArray;
  UnownedPtr<std::vector<cppgc::Persistent<CXFA_Node>>> m_pScriptNodeArray;
  std::unique_ptr<CFXJSE_NodeHelper> const m_NodeHelper;
  std::unique_ptr<CFXJSE_ResolveProcessor> const m_ResolveProcessor;
  std::unique_ptr<CFXJSE_FormCalcContext> m_FormCalcContext;
  cppgc::Persistent<CXFA_Object> m_pThisObject;
  XFA_AttributeValue m_eRunAtType = XFA_AttributeValue::Client;
  bool m_bResolvingNodes = false;
};

#endif  //  FXJS_XFA_CFXJSE_ENGINE_H_
