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

#include "core/fxcrt/include/fx_ext.h"
#include "xfa/fxfa/fm2js/xfa_fm2jsapi.h"
#include "xfa/fxfa/parser/xfa_basic_imp.h"
#include "xfa/fxfa/parser/xfa_docdata.h"
#include "xfa/fxfa/parser/xfa_doclayout.h"
#include "xfa/fxfa/parser/xfa_document.h"
#include "xfa/fxfa/parser/xfa_document_layout_imp.h"
#include "xfa/fxfa/parser/xfa_localemgr.h"
#include "xfa/fxfa/parser/xfa_object.h"
#include "xfa/fxfa/parser/xfa_parser.h"
#include "xfa/fxfa/parser/xfa_script.h"
#include "xfa/fxfa/parser/xfa_script_datawindow.h"
#include "xfa/fxfa/parser/xfa_script_eventpseudomodel.h"
#include "xfa/fxfa/parser/xfa_script_hostpseudomodel.h"
#include "xfa/fxfa/parser/xfa_script_layoutpseudomodel.h"
#include "xfa/fxfa/parser/xfa_script_logpseudomodel.h"
#include "xfa/fxfa/parser/xfa_script_signaturepseudomodel.h"
#include "xfa/fxfa/parser/xfa_utils.h"

CXFA_Document::CXFA_Document(IXFA_DocParser* pParser)
    : m_pParser(pParser),
      m_pScriptContext(nullptr),
      m_pLayoutProcessor(nullptr),
      m_pRootNode(nullptr),
      m_pLocalMgr(nullptr),
      m_pScriptDataWindow(nullptr),
      m_pScriptEvent(nullptr),
      m_pScriptHost(nullptr),
      m_pScriptLog(nullptr),
      m_pScriptLayout(nullptr),
      m_pScriptSignature(nullptr),
      m_eCurVersionMode(XFA_VERSION_DEFAULT),
      m_dwDocFlags(0) {
  ASSERT(m_pParser);
}
CXFA_Document::~CXFA_Document() {
  delete m_pRootNode;
  PurgeNodes();
}
void CXFA_Document::ClearLayoutData() {
  if (m_pLayoutProcessor) {
    delete m_pLayoutProcessor;
    m_pLayoutProcessor = NULL;
  }
  if (m_pScriptContext) {
    m_pScriptContext->Release();
    m_pScriptContext = NULL;
  }
  if (m_pLocalMgr) {
    delete m_pLocalMgr;
    m_pLocalMgr = NULL;
  }
  if (m_pScriptDataWindow) {
    delete m_pScriptDataWindow;
    m_pScriptDataWindow = NULL;
  }
  if (m_pScriptEvent) {
    delete m_pScriptEvent;
    m_pScriptEvent = NULL;
  }
  if (m_pScriptHost) {
    delete m_pScriptHost;
    m_pScriptHost = NULL;
  }
  if (m_pScriptLog) {
    delete m_pScriptLog;
    m_pScriptLog = NULL;
  }
  if (m_pScriptLayout) {
    delete m_pScriptLayout;
    m_pScriptLayout = NULL;
  }
  if (m_pScriptSignature) {
    delete m_pScriptSignature;
    m_pScriptSignature = NULL;
  }
}
void CXFA_Document::SetRoot(CXFA_Node* pNewRoot) {
  if (m_pRootNode) {
    AddPurgeNode(m_pRootNode);
  }
  m_pRootNode = pNewRoot;
  RemovePurgeNode(pNewRoot);
}
IXFA_Notify* CXFA_Document::GetNotify() const {
  return m_pParser->GetNotify();
}
CXFA_Object* CXFA_Document::GetXFAObject(const CFX_WideStringC& wsNodeName) {
  return GetXFAObject(
      FX_HashCode_String_GetW(wsNodeName.GetPtr(), wsNodeName.GetLength()));
}
CXFA_Object* CXFA_Document::GetXFAObject(FX_DWORD dwNodeNameHash) {
  switch (dwNodeNameHash) {
    case XFA_HASHCODE_Data: {
      CXFA_Node* pDatasetsNode = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
      if (!pDatasetsNode) {
        return NULL;
      }
      for (CXFA_Node* pDatasetsChild =
               pDatasetsNode->GetFirstChildByClass(XFA_ELEMENT_DataGroup);
           pDatasetsChild;
           pDatasetsChild =
               pDatasetsChild->GetNextSameClassSibling(XFA_ELEMENT_DataGroup)) {
        if (pDatasetsChild->GetNameHash() != XFA_HASHCODE_Data) {
          continue;
        }
        CFX_WideString wsNamespaceURI;
        if (!pDatasetsChild->TryNamespace(wsNamespaceURI)) {
          continue;
        }
        CFX_WideString wsDatasetsURI;
        if (!pDatasetsNode->TryNamespace(wsDatasetsURI)) {
          continue;
        }
        if (wsNamespaceURI == wsDatasetsURI) {
          return pDatasetsChild;
        }
      }
    }
      return NULL;
    case XFA_HASHCODE_Record: {
      CXFA_Node* pData = ToNode(GetXFAObject(XFA_HASHCODE_Data));
      return pData ? pData->GetFirstChildByClass(XFA_ELEMENT_DataGroup) : NULL;
    }
    case XFA_HASHCODE_DataWindow: {
      if (m_pScriptDataWindow == NULL) {
        m_pScriptDataWindow = new CScript_DataWindow(this);
      }
      return m_pScriptDataWindow;
    }
    case XFA_HASHCODE_Event: {
      if (m_pScriptEvent == NULL) {
        m_pScriptEvent = new CScript_EventPseudoModel(this);
      }
      return m_pScriptEvent;
    }
    case XFA_HASHCODE_Host: {
      if (m_pScriptHost == NULL) {
        m_pScriptHost = new CScript_HostPseudoModel(this);
      }
      return m_pScriptHost;
    }
    case XFA_HASHCODE_Log: {
      if (m_pScriptLog == NULL) {
        m_pScriptLog = new CScript_LogPseudoModel(this);
      }
      return m_pScriptLog;
    }
    case XFA_HASHCODE_Signature: {
      if (m_pScriptSignature == NULL) {
        m_pScriptSignature = new CScript_SignaturePseudoModel(this);
      }
      return m_pScriptSignature;
    }
    case XFA_HASHCODE_Layout: {
      if (m_pScriptLayout == NULL) {
        m_pScriptLayout = new CScript_LayoutPseudoModel(this);
      }
      return m_pScriptLayout;
    }
    default:
      return m_pRootNode->GetFirstChildByName(dwNodeNameHash);
  }
}
CXFA_Node* CXFA_Document::CreateNode(FX_DWORD dwPacket, XFA_ELEMENT eElement) {
  return CreateNode(XFA_GetPacketByID(dwPacket), eElement);
}
CXFA_Node* CXFA_Document::CreateNode(const XFA_PACKETINFO* pPacket,
                                     XFA_ELEMENT eElement) {
  if (pPacket == NULL) {
    return NULL;
  }
  const XFA_ELEMENTINFO* pElement = XFA_GetElementByID(eElement);
  if (pElement && (pElement->dwPackets & pPacket->eName)) {
    CXFA_Node* pNode = new CXFA_Node(this, pPacket->eName, pElement->eName);
    if (pNode) {
      AddPurgeNode(pNode);
    }
    return pNode;
  }
  return NULL;
}
void CXFA_Document::AddPurgeNode(CXFA_Node* pNode) {
  m_rgPurgeNodes.Add(pNode);
}
FX_BOOL CXFA_Document::RemovePurgeNode(CXFA_Node* pNode) {
  return m_rgPurgeNodes.RemoveKey(pNode);
}
void CXFA_Document::PurgeNodes() {
  FX_POSITION psNode = m_rgPurgeNodes.GetStartPosition();
  while (psNode) {
    CXFA_Node* pNode;
    m_rgPurgeNodes.GetNextAssoc(psNode, pNode);
    delete pNode;
  }
  m_rgPurgeNodes.RemoveAll();
}
void CXFA_Document::SetFlag(FX_DWORD dwFlag, FX_BOOL bOn) {
  if (bOn) {
    m_dwDocFlags |= dwFlag;
  } else {
    m_dwDocFlags &= ~dwFlag;
  }
}
FX_BOOL CXFA_Document::IsInteractive() {
  if (m_dwDocFlags & XFA_DOCFLAG_HasInteractive) {
    return m_dwDocFlags & XFA_DOCFLAG_Interactive;
  }
  CXFA_Node* pConfig = ToNode(GetXFAObject(XFA_HASHCODE_Config));
  if (!pConfig) {
    return FALSE;
  }
  CFX_WideString wsInteractive;
  CXFA_Node* pPresent = pConfig->GetFirstChildByClass(XFA_ELEMENT_Present);
  if (!pPresent) {
    return FALSE;
  }
  CXFA_Node* pPDF = pPresent->GetFirstChildByClass(XFA_ELEMENT_Pdf);
  if (!pPDF) {
    return FALSE;
  }
  CXFA_Node* pInteractive = pPDF->GetChild(0, XFA_ELEMENT_Interactive);
  if (pInteractive) {
    m_dwDocFlags |= XFA_DOCFLAG_HasInteractive;
    if (pInteractive->TryContent(wsInteractive) &&
        wsInteractive == FX_WSTRC(L"1")) {
      m_dwDocFlags |= XFA_DOCFLAG_Interactive;
      return TRUE;
    }
  }
  return FALSE;
}
CXFA_LocaleMgr* CXFA_Document::GetLocalMgr() {
  if (!m_pLocalMgr) {
    CFX_WideString wsLanguage;
    GetParser()->GetNotify()->GetAppProvider()->GetLanguage(wsLanguage);
    m_pLocalMgr = new CXFA_LocaleMgr(
        ToNode(GetXFAObject(XFA_HASHCODE_LocaleSet)), wsLanguage);
  }
  return m_pLocalMgr;
}
IXFA_ScriptContext* CXFA_Document::InitScriptContext(FXJSE_HRUNTIME hRuntime) {
  if (!m_pScriptContext) {
    m_pScriptContext = XFA_ScriptContext_Create(this);
  }
  m_pScriptContext->Initialize(hRuntime);
  return m_pScriptContext;
}
IXFA_ScriptContext* CXFA_Document::GetScriptContext() {
  if (!m_pScriptContext) {
    m_pScriptContext = XFA_ScriptContext_Create(this);
  }
  return m_pScriptContext;
}
XFA_VERSION CXFA_Document::RecognizeXFAVersionNumber(
    CFX_WideString& wsTemplateNS) {
  CFX_WideStringC wsTemplateURIPrefix =
      XFA_GetPacketByIndex(XFA_PACKET_Template)->pURI;
  FX_STRSIZE nPrefixLength = wsTemplateURIPrefix.GetLength();
  if (CFX_WideStringC(wsTemplateNS, wsTemplateNS.GetLength()) !=
      wsTemplateURIPrefix) {
    return XFA_VERSION_UNKNOWN;
  }
  FX_STRSIZE nDotPos = wsTemplateNS.Find('.', nPrefixLength);
  if (nDotPos == (FX_STRSIZE)-1) {
    return XFA_VERSION_UNKNOWN;
  }
  int8_t iMajor =
      FXSYS_wtoi(wsTemplateNS.Mid(nPrefixLength, nDotPos - nPrefixLength));
  int8_t iMinor = FXSYS_wtoi(
      wsTemplateNS.Mid(nDotPos + 1, wsTemplateNS.GetLength() - nDotPos - 2));
  XFA_VERSION eVersion = (XFA_VERSION)((int32_t)iMajor * 100 + iMinor);
  if (eVersion < XFA_VERSION_MIN || eVersion > XFA_VERSION_MAX) {
    return XFA_VERSION_UNKNOWN;
  }
  m_eCurVersionMode = eVersion;
  return eVersion;
}
CXFA_Node* CXFA_Document::GetNodeByID(CXFA_Node* pRoot,
                                      const CFX_WideStringC& wsID) {
  if (!pRoot || wsID.IsEmpty()) {
    return NULL;
  }
  CXFA_NodeIterator sIterator(pRoot);
  for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
       pNode = sIterator.MoveToNext()) {
    CFX_WideStringC wsIDVal;
    if (pNode->TryCData(XFA_ATTRIBUTE_Id, wsIDVal) && !wsIDVal.IsEmpty()) {
      if (wsIDVal == wsID) {
        return pNode;
      }
    }
  }
  return NULL;
}
static void XFA_ProtoMerge_MergeNodeRecurse(CXFA_Document* pDocument,
                                            CXFA_Node* pDestNodeParent,
                                            CXFA_Node* pProtoNode) {
  CXFA_Node* pExistingNode = NULL;
  for (CXFA_Node* pFormChild =
           pDestNodeParent->GetNodeItem(XFA_NODEITEM_FirstChild);
       pFormChild;
       pFormChild = pFormChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
    if (pFormChild->GetClassID() == pProtoNode->GetClassID() &&
        pFormChild->GetNameHash() == pProtoNode->GetNameHash() &&
        pFormChild->HasFlag(XFA_NODEFLAG_UnusedNode)) {
      pFormChild->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE);
      pExistingNode = pFormChild;
      break;
    }
  }
  if (pExistingNode) {
    pExistingNode->SetTemplateNode(pProtoNode);
    for (CXFA_Node* pTemplateChild =
             pProtoNode->GetNodeItem(XFA_NODEITEM_FirstChild);
         pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem(
                             XFA_NODEITEM_NextSibling)) {
      XFA_ProtoMerge_MergeNodeRecurse(pDocument, pExistingNode, pTemplateChild);
    }
    return;
  }
  CXFA_Node* pNewNode = pProtoNode->Clone(TRUE);
  pNewNode->SetTemplateNode(pProtoNode);
  pDestNodeParent->InsertChild(pNewNode, NULL);
}
static void XFA_ProtoMerge_MergeNode(CXFA_Document* pDocument,
                                     CXFA_Node* pDestNode,
                                     CXFA_Node* pProtoNode) {
  {
    CXFA_NodeIterator sIterator(pDestNode);
    for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
         pNode = sIterator.MoveToNext()) {
      pNode->SetFlag(XFA_NODEFLAG_UnusedNode);
    }
  }
  pDestNode->SetTemplateNode(pProtoNode);
  for (CXFA_Node* pTemplateChild =
           pProtoNode->GetNodeItem(XFA_NODEITEM_FirstChild);
       pTemplateChild;
       pTemplateChild = pTemplateChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
    XFA_ProtoMerge_MergeNodeRecurse(pDocument, pDestNode, pTemplateChild);
  }
  {
    CXFA_NodeIterator sIterator(pDestNode);
    for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
         pNode = sIterator.MoveToNext()) {
      pNode->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE);
    }
  }
}
void CXFA_Document::DoProtoMerge() {
  CXFA_Node* pTemplateRoot = ToNode(GetXFAObject(XFA_HASHCODE_Template));
  if (!pTemplateRoot) {
    return;
  }
  CFX_MapPtrTemplate<FX_DWORD, CXFA_Node*> mIDMap;
  CXFA_NodeSet sUseNodes;
  CXFA_NodeIterator sIterator(pTemplateRoot);
  for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
       pNode = sIterator.MoveToNext()) {
    CFX_WideStringC wsIDVal;
    if (pNode->TryCData(XFA_ATTRIBUTE_Id, wsIDVal) && !wsIDVal.IsEmpty()) {
      mIDMap[FX_HashCode_String_GetW(wsIDVal.GetPtr(), wsIDVal.GetLength())] =
          pNode;
    }
    CFX_WideStringC wsUseVal;
    if (pNode->TryCData(XFA_ATTRIBUTE_Use, wsUseVal) && !wsUseVal.IsEmpty()) {
      sUseNodes.Add(pNode);
    } else if (pNode->TryCData(XFA_ATTRIBUTE_Usehref, wsUseVal) &&
               !wsUseVal.IsEmpty()) {
      sUseNodes.Add(pNode);
    }
  }
  FX_POSITION pos = sUseNodes.GetStartPosition();
  while (pos) {
    CXFA_Node* pUseHrefNode = NULL;
    sUseNodes.GetNextAssoc(pos, pUseHrefNode);
    CFX_WideString wsUseVal;
    CFX_WideStringC wsURI, wsID, wsSOM;
    if (pUseHrefNode->TryCData(XFA_ATTRIBUTE_Usehref, wsUseVal) &&
        !wsUseVal.IsEmpty()) {
      FX_STRSIZE uSharpPos = wsUseVal.Find('#');
      if (uSharpPos < 0) {
        wsURI = wsUseVal;
      } else {
        wsURI = CFX_WideStringC((const FX_WCHAR*)wsUseVal, uSharpPos);
        FX_STRSIZE uLen = wsUseVal.GetLength();
        if (uLen >= uSharpPos + 5 &&
            CFX_WideStringC((const FX_WCHAR*)wsUseVal + uSharpPos, 5) ==
                FX_WSTRC(L"#som(") &&
            wsUseVal[uLen - 1] == ')') {
          wsSOM = CFX_WideStringC((const FX_WCHAR*)wsUseVal + uSharpPos + 5,
                                  uLen - 1 - uSharpPos - 5);
        } else {
          wsID = CFX_WideStringC((const FX_WCHAR*)wsUseVal + uSharpPos + 1,
                                 uLen - uSharpPos - 1);
        }
      }
    } else if (pUseHrefNode->TryCData(XFA_ATTRIBUTE_Use, wsUseVal) &&
               !wsUseVal.IsEmpty()) {
      if (wsUseVal[0] == '#') {
        wsID = CFX_WideStringC((const FX_WCHAR*)wsUseVal + 1,
                               wsUseVal.GetLength() - 1);
      } else {
        wsSOM =
            CFX_WideStringC((const FX_WCHAR*)wsUseVal, wsUseVal.GetLength());
      }
    }
    if (!wsURI.IsEmpty() && wsURI != FX_WSTRC(L".")) {
      continue;
    }
    CXFA_Node* pProtoNode = NULL;
    if (!wsSOM.IsEmpty()) {
      FX_DWORD dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
                        XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
                        XFA_RESOLVENODE_Siblings;
      XFA_RESOLVENODE_RS resoveNodeRS;
      int32_t iRet = m_pScriptContext->ResolveObjects(pUseHrefNode, wsSOM,
                                                      resoveNodeRS, dwFlag);
      if (iRet > 0 && resoveNodeRS.nodes[0]->IsNode()) {
        pProtoNode = resoveNodeRS.nodes[0]->AsNode();
      }
    } else if (!wsID.IsEmpty()) {
      if (!mIDMap.Lookup(
              FX_HashCode_String_GetW(wsID.GetPtr(), wsID.GetLength()),
              pProtoNode)) {
        continue;
      }
    }
    if (!pProtoNode) {
      continue;
    }
    XFA_ProtoMerge_MergeNode(this, pUseHrefNode, pProtoNode);
  }
}
