// 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/app/xfa_ffnotify.h"
#include "xfa/fxfa/parser/cscript_datawindow.h"
#include "xfa/fxfa/parser/cscript_eventpseudomodel.h"
#include "xfa/fxfa/parser/cscript_hostpseudomodel.h"
#include "xfa/fxfa/parser/cscript_layoutpseudomodel.h"
#include "xfa/fxfa/parser/cscript_logpseudomodel.h"
#include "xfa/fxfa/parser/cscript_signaturepseudomodel.h"
#include "xfa/fxfa/parser/cxfa_document_parser.h"
#include "xfa/fxfa/parser/cxfa_scriptcontext.h"
#include "xfa/fxfa/parser/xfa_basic_imp.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_resolvenode_rs.h"
#include "xfa/fxfa/parser/xfa_utils.h"

CXFA_Document::CXFA_Document(CXFA_DocumentParser* 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() {
  delete m_pLayoutProcessor;
  m_pLayoutProcessor = nullptr;
  delete m_pScriptContext;
  m_pScriptContext = nullptr;
  delete m_pLocalMgr;
  m_pLocalMgr = nullptr;
  delete m_pScriptDataWindow;
  m_pScriptDataWindow = nullptr;
  delete m_pScriptEvent;
  m_pScriptEvent = nullptr;
  delete m_pScriptHost;
  m_pScriptHost = nullptr;
  delete m_pScriptLog;
  m_pScriptLog = nullptr;
  delete m_pScriptLayout;
  m_pScriptLayout = nullptr;
  delete m_pScriptSignature;
  m_pScriptSignature = nullptr;
}

void CXFA_Document::SetRoot(CXFA_Node* pNewRoot) {
  if (m_pRootNode) {
    AddPurgeNode(m_pRootNode);
  }
  m_pRootNode = pNewRoot;
  RemovePurgeNode(pNewRoot);
}

CFDE_XMLDoc* CXFA_Document::GetXMLDoc() const {
  return m_pParser->GetXMLDoc();
}

CXFA_FFNotify* CXFA_Document::GetNotify() const {
  return m_pParser->GetNotify();
}

CXFA_Object* CXFA_Document::GetXFAObject(XFA_HashCode dwNodeNameHash) {
  switch (dwNodeNameHash) {
    case XFA_HASHCODE_Data: {
      CXFA_Node* pDatasetsNode = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
      if (!pDatasetsNode) {
        return nullptr;
      }
      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 nullptr;
    }
    case XFA_HASHCODE_Record: {
      CXFA_Node* pData = ToNode(GetXFAObject(XFA_HASHCODE_Data));
      return pData ? pData->GetFirstChildByClass(XFA_Element::DataGroup)
                   : nullptr;
    }
    case XFA_HASHCODE_DataWindow: {
      if (!m_pScriptDataWindow)
        m_pScriptDataWindow = new CScript_DataWindow(this);
      return m_pScriptDataWindow;
    }
    case XFA_HASHCODE_Event: {
      if (!m_pScriptEvent)
        m_pScriptEvent = new CScript_EventPseudoModel(this);
      return m_pScriptEvent;
    }
    case XFA_HASHCODE_Host: {
      if (!m_pScriptHost)
        m_pScriptHost = new CScript_HostPseudoModel(this);
      return m_pScriptHost;
    }
    case XFA_HASHCODE_Log: {
      if (!m_pScriptLog)
        m_pScriptLog = new CScript_LogPseudoModel(this);
      return m_pScriptLog;
    }
    case XFA_HASHCODE_Signature: {
      if (!m_pScriptSignature)
        m_pScriptSignature = new CScript_SignaturePseudoModel(this);
      return m_pScriptSignature;
    }
    case XFA_HASHCODE_Layout: {
      if (!m_pScriptLayout)
        m_pScriptLayout = new CScript_LayoutPseudoModel(this);
      return m_pScriptLayout;
    }
    default:
      return m_pRootNode->GetFirstChildByName(dwNodeNameHash);
  }
}
CXFA_Node* CXFA_Document::CreateNode(uint32_t dwPacket, XFA_Element eElement) {
  return CreateNode(XFA_GetPacketByID(dwPacket), eElement);
}

CXFA_Node* CXFA_Document::CreateNode(const XFA_PACKETINFO* pPacket,
                                     XFA_Element eElement) {
  if (!pPacket)
    return nullptr;

  const XFA_ELEMENTINFO* pElement = XFA_GetElementByID(eElement);
  if (pElement && (pElement->dwPackets & pPacket->eName)) {
    CXFA_Node* pNode =
        new CXFA_Node(this, pPacket->eName, pElement->eObjectType,
                      pElement->eName, pElement->pName);
    AddPurgeNode(pNode);
    return pNode;
  }

  return nullptr;
}

void CXFA_Document::AddPurgeNode(CXFA_Node* pNode) {
  m_PurgeNodes.insert(pNode);
}

FX_BOOL CXFA_Document::RemovePurgeNode(CXFA_Node* pNode) {
  return !!m_PurgeNodes.erase(pNode);
}

void CXFA_Document::PurgeNodes() {
  for (CXFA_Node* pNode : m_PurgeNodes)
    delete pNode;

  m_PurgeNodes.clear();
}

void CXFA_Document::SetFlag(uint32_t 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;
    GetNotify()->GetAppProvider()->GetLanguage(wsLanguage);
    m_pLocalMgr = new CXFA_LocaleMgr(
        ToNode(GetXFAObject(XFA_HASHCODE_LocaleSet)), wsLanguage);
  }
  return m_pLocalMgr;
}
CXFA_ScriptContext* CXFA_Document::InitScriptContext(v8::Isolate* pIsolate) {
  if (!m_pScriptContext)
    m_pScriptContext = new CXFA_ScriptContext(this);
  m_pScriptContext->Initialize(pIsolate);
  return m_pScriptContext;
}
CXFA_ScriptContext* CXFA_Document::GetScriptContext() {
  if (!m_pScriptContext)
    m_pScriptContext = new CXFA_ScriptContext(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.c_str(), 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).c_str());
  int8_t iMinor = FXSYS_wtoi(
      wsTemplateNS.Mid(nDotPos + 1, wsTemplateNS.GetLength() - nDotPos - 2)
          .c_str());
  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 nullptr;
  }
  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 nullptr;
}
static void XFA_ProtoMerge_MergeNodeRecurse(CXFA_Document* pDocument,
                                            CXFA_Node* pDestNodeParent,
                                            CXFA_Node* pProtoNode) {
  CXFA_Node* pExistingNode = nullptr;
  for (CXFA_Node* pFormChild =
           pDestNodeParent->GetNodeItem(XFA_NODEITEM_FirstChild);
       pFormChild;
       pFormChild = pFormChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
    if (pFormChild->GetElementType() == pProtoNode->GetElementType() &&
        pFormChild->GetNameHash() == pProtoNode->GetNameHash() &&
        pFormChild->IsUnusedNode()) {
      pFormChild->ClearFlag(XFA_NodeFlag_UnusedNode);
      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, nullptr);
}
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, true);
    }
  }
  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->ClearFlag(XFA_NodeFlag_UnusedNode);
    }
  }
}
void CXFA_Document::DoProtoMerge() {
  CXFA_Node* pTemplateRoot = ToNode(GetXFAObject(XFA_HASHCODE_Template));
  if (!pTemplateRoot) {
    return;
  }
  CFX_MapPtrTemplate<uint32_t, 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_GetW(wsIDVal, false)] = pNode;
    }
    CFX_WideStringC wsUseVal;
    if (pNode->TryCData(XFA_ATTRIBUTE_Use, wsUseVal) && !wsUseVal.IsEmpty()) {
      sUseNodes.insert(pNode);
    } else if (pNode->TryCData(XFA_ATTRIBUTE_Usehref, wsUseVal) &&
               !wsUseVal.IsEmpty()) {
      sUseNodes.insert(pNode);
    }
  }
  for (CXFA_Node* pUseHrefNode : sUseNodes) {
    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.AsStringC();
      } else {
        wsURI = CFX_WideStringC(wsUseVal.c_str(), uSharpPos);
        FX_STRSIZE uLen = wsUseVal.GetLength();
        if (uLen >= uSharpPos + 5 &&
            CFX_WideStringC(wsUseVal.c_str() + uSharpPos, 5) ==
                FX_WSTRC(L"#som(") &&
            wsUseVal[uLen - 1] == ')') {
          wsSOM = CFX_WideStringC(wsUseVal.c_str() + uSharpPos + 5,
                                  uLen - 1 - uSharpPos - 5);
        } else {
          wsID = CFX_WideStringC(wsUseVal.c_str() + uSharpPos + 1,
                                 uLen - uSharpPos - 1);
        }
      }
    } else if (pUseHrefNode->TryCData(XFA_ATTRIBUTE_Use, wsUseVal) &&
               !wsUseVal.IsEmpty()) {
      if (wsUseVal[0] == '#') {
        wsID = CFX_WideStringC(wsUseVal.c_str() + 1, wsUseVal.GetLength() - 1);
      } else {
        wsSOM = CFX_WideStringC(wsUseVal.c_str(), wsUseVal.GetLength());
      }
    }
    if (!wsURI.IsEmpty() && wsURI != FX_WSTRC(L".")) {
      continue;
    }
    CXFA_Node* pProtoNode = nullptr;
    if (!wsSOM.IsEmpty()) {
      uint32_t 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_GetW(wsID, false), pProtoNode)) {
        continue;
      }
    }
    if (!pProtoNode) {
      continue;
    }
    XFA_ProtoMerge_MergeNode(this, pUseHrefNode, pProtoNode);
  }
}
