// Copyright 2014 PDFium Authors. All rights reserved.
// 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 XFA_FXFA_PARSER_CXFA_DOCUMENT_H_
#define XFA_FXFA_PARSER_CXFA_DOCUMENT_H_

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

#include "core/fxcrt/unowned_ptr.h"
#include "fxjs/gc/heap.h"
#include "third_party/base/optional.h"
#include "third_party/base/span.h"
#include "v8/include/cppgc/garbage-collected.h"
#include "v8/include/cppgc/member.h"
#include "v8/include/cppgc/persistent.h"
#include "v8/include/cppgc/visitor.h"
#include "xfa/fxfa/fxfa.h"
#include "xfa/fxfa/parser/cxfa_localemgr.h"
#include "xfa/fxfa/parser/cxfa_nodeowner.h"

class CFXJSE_Engine;
class CJS_Runtime;
class CScript_DataWindow;
class CScript_EventPseudoModel;
class CScript_HostPseudoModel;
class CScript_LayoutPseudoModel;
class CScript_LogPseudoModel;
class CScript_SignaturePseudoModel;
class CXFA_FFNotify;
class CXFA_Node;
class CXFA_Object;

namespace cppgc {
class Heap;
}  // namespace cppgc

enum XFA_VERSION {
  XFA_VERSION_UNKNOWN = 0,
  XFA_VERSION_200 = 200,
  XFA_VERSION_202 = 202,
  XFA_VERSION_204 = 204,
  XFA_VERSION_205 = 205,
  XFA_VERSION_206 = 206,
  XFA_VERSION_207 = 207,
  XFA_VERSION_208 = 208,
  XFA_VERSION_300 = 300,
  XFA_VERSION_301 = 301,
  XFA_VERSION_303 = 303,
  XFA_VERSION_306 = 306,
  XFA_VERSION_DEFAULT = XFA_VERSION_303,
  XFA_VERSION_MIN = 200,
  XFA_VERSION_MAX = 400,
};

class CXFA_Document final : public cppgc::GarbageCollected<CXFA_Document> {
 public:
  class LayoutProcessorIface
      : public cppgc::GarbageCollected<LayoutProcessorIface> {
   public:
    LayoutProcessorIface();
    virtual ~LayoutProcessorIface();

    virtual void Trace(cppgc::Visitor* visitor) const;
    virtual void SetForceRelayout(bool enable) = 0;
    virtual void AddChangedContainer(CXFA_Node* pContainer) = 0;

    void SetDocument(CXFA_Document* pDocument) { m_pDocument = pDocument; }
    CXFA_Document* GetDocument() const { return m_pDocument; }

   private:
    cppgc::Member<CXFA_Document> m_pDocument;
  };

  CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
  ~CXFA_Document();

  void Trace(cppgc::Visitor* visitor) const;

  bool HasScriptContext() const { return !!m_pScriptContext; }
  CFXJSE_Engine* InitScriptContext(CJS_Runtime* fxjs_runtime);

  // Only safe to call in situations where the context is known to exist,
  // and always returns non-NULL in those situations. In other words, we have
  // to call InitScriptContext() first to avoid a situation where the context
  // won't have an isolate set into it.
  CFXJSE_Engine* GetScriptContext() const;

  CXFA_FFNotify* GetNotify() const { return notify_.Get(); }
  CXFA_NodeOwner* GetNodeOwner() { return node_owner_; }
  cppgc::Heap* GetHeap() const;
  CXFA_LocaleMgr* GetLocaleMgr();
  CXFA_Object* GetXFAObject(XFA_HashCode wsNodeNameHash);
  CXFA_Node* GetNodeByID(CXFA_Node* pRoot, WideStringView wsID) const;
  CXFA_Node* GetNotBindNode(
      pdfium::span<cppgc::Member<CXFA_Object>> arrayNodes) const;

  LayoutProcessorIface* GetLayoutProcessor() const {
    return m_pLayoutProcessor;
  }
  CXFA_Node* GetRoot() const { return m_pRootNode; }
  void SetRoot(CXFA_Node* pNewRoot) { m_pRootNode = pNewRoot; }

  bool is_strict_scoping() const { return m_bStrictScoping; }
  void set_is_strict_scoping() { m_bStrictScoping = true; }

  bool is_scripting() const { return m_bScripting; }
  void set_is_scripting() { m_bScripting = true; }

  bool IsInteractive();
  XFA_VERSION GetCurVersionMode() const { return m_eCurVersionMode; }
  XFA_VERSION RecognizeXFAVersionNumber(const WideString& wsTemplateNS);
  FormType GetFormType() const;

  CXFA_Node* CreateNode(XFA_PacketType packet, XFA_Element eElement);

  void DoProtoMerge();
  void DoDataMerge();
  void DoDataRemerge(bool bDoDataMerge);
  CXFA_Node* DataMerge_CopyContainer(CXFA_Node* pTemplateNode,
                                     CXFA_Node* pFormNode,
                                     CXFA_Node* pDataScope,
                                     bool bOneInstance,
                                     bool bDataMerge,
                                     bool bUpLevel);
  void DataMerge_UpdateBindingRelations(CXFA_Node* pFormUpdateRoot);

  void ClearLayoutData();

  CXFA_Node* GetGlobalBinding(uint32_t dwNameHash);
  void RegisterGlobalBinding(uint32_t dwNameHash, CXFA_Node* pDataNode);

  size_t GetPendingNodesCount() const;
  CXFA_Node* GetPendingNodeAtIndex(size_t index) const;
  void AppendPendingNode(CXFA_Node* node);
  void ClearPendingNodes();
  void SetPendingNodesUnusedAndUnbound();

 private:
  CXFA_Document(CXFA_FFNotify* notify,
                cppgc::Heap* heap,
                LayoutProcessorIface* pLayout);

  UnownedPtr<cppgc::Heap> heap_;
  cppgc::Member<CXFA_FFNotify> const notify_;
  cppgc::Member<CXFA_NodeOwner> const node_owner_;
  cppgc::Member<CXFA_Node> m_pRootNode;
  std::unique_ptr<CFXJSE_Engine> m_pScriptContext;
  cppgc::Member<LayoutProcessorIface> m_pLayoutProcessor;
  cppgc::Member<CXFA_LocaleMgr> m_pLocaleMgr;
  cppgc::Member<CScript_DataWindow> m_pScriptDataWindow;
  cppgc::Member<CScript_EventPseudoModel> m_pScriptEvent;
  cppgc::Member<CScript_HostPseudoModel> m_pScriptHost;
  cppgc::Member<CScript_LogPseudoModel> m_pScriptLog;
  cppgc::Member<CScript_LayoutPseudoModel> m_pScriptLayout;
  cppgc::Member<CScript_SignaturePseudoModel> m_pScriptSignature;
  std::map<uint32_t, cppgc::Member<CXFA_Node>> m_rgGlobalBinding;
  std::vector<cppgc::Member<CXFA_Node>> m_pPendingPageSet;
  XFA_VERSION m_eCurVersionMode = XFA_VERSION_DEFAULT;
  Optional<bool> m_Interactive;
  bool m_bStrictScoping = false;
  bool m_bScripting = false;
};

#endif  // XFA_FXFA_PARSER_CXFA_DOCUMENT_H_
