// 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 "xfa/fxfa/parser/cxfa_nodehelper.h"

#include "core/fxcrt/fx_extension.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_localemgr.h"
#include "xfa/fxfa/parser/cxfa_node.h"
#include "xfa/fxfa/parser/cxfa_scriptcontext.h"
#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
#include "xfa/fxfa/parser/xfa_utils.h"

CXFA_NodeHelper::CXFA_NodeHelper()
    : m_eLastCreateType(XFA_Element::DataValue),
      m_pCreateParent(nullptr),
      m_iCreateCount(0),
      m_iCreateFlag(XFA_RESOLVENODE_RSTYPE_CreateNodeOne),
      m_iCurAllStart(-1),
      m_pAllStartParent(nullptr) {}

CXFA_NodeHelper::~CXFA_NodeHelper() {}

CXFA_Node* CXFA_NodeHelper::ResolveNodes_GetOneChild(CXFA_Node* parent,
                                                     const wchar_t* pwsName,
                                                     bool bIsClassName) {
  if (!parent)
    return nullptr;

  std::vector<CXFA_Node*> siblings;
  uint32_t uNameHash = FX_HashCode_GetW(WideStringView(pwsName), false);
  NodeAcc_TraverseAnySiblings(parent, uNameHash, &siblings, bIsClassName);
  return !siblings.empty() ? siblings[0] : nullptr;
}

int32_t CXFA_NodeHelper::CountSiblings(CXFA_Node* pNode,
                                       XFA_LOGIC_TYPE eLogicType,
                                       std::vector<CXFA_Node*>* pSiblings,
                                       bool bIsClassName) {
  if (!pNode)
    return 0;
  CXFA_Node* parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent);
  if (!parent)
    return 0;
  const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement(
      parent->GetElementType(), pNode->GetElementType(), XFA_XDPPACKET_UNKNOWN);
  if (!pProperty && eLogicType == XFA_LOGIC_Transparent) {
    parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent);
    if (!parent)
      return 0;
  }
  if (bIsClassName) {
    return NodeAcc_TraverseSiblings(parent, pNode->GetClassHashCode(),
                                    pSiblings, eLogicType, bIsClassName);
  }
  return NodeAcc_TraverseSiblings(parent, pNode->GetNameHash(), pSiblings,
                                  eLogicType, bIsClassName);
}

int32_t CXFA_NodeHelper::NodeAcc_TraverseAnySiblings(
    CXFA_Node* parent,
    uint32_t dNameHash,
    std::vector<CXFA_Node*>* pSiblings,
    bool bIsClassName) {
  if (!parent || !pSiblings)
    return 0;

  int32_t nCount = 0;
  for (CXFA_Node* child : parent->GetNodeList(XFA_NODEFILTER_Properties)) {
    if (bIsClassName) {
      if (child->GetClassHashCode() == dNameHash) {
        pSiblings->push_back(child);
        nCount++;
      }
    } else {
      if (child->GetNameHash() == dNameHash) {
        pSiblings->push_back(child);
        nCount++;
      }
    }
    if (nCount > 0)
      return nCount;

    nCount +=
        NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName);
  }
  for (CXFA_Node* child : parent->GetNodeList(XFA_NODEFILTER_Children)) {
    if (bIsClassName) {
      if (child->GetClassHashCode() == dNameHash) {
        pSiblings->push_back(child);
        nCount++;
      }
    } else {
      if (child->GetNameHash() == dNameHash) {
        pSiblings->push_back(child);
        nCount++;
      }
    }
    if (nCount > 0)
      return nCount;

    nCount +=
        NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName);
  }
  return nCount;
}

int32_t CXFA_NodeHelper::NodeAcc_TraverseSiblings(
    CXFA_Node* parent,
    uint32_t dNameHash,
    std::vector<CXFA_Node*>* pSiblings,
    XFA_LOGIC_TYPE eLogicType,
    bool bIsClassName,
    bool bIsFindProperty) {
  if (!parent || !pSiblings)
    return 0;

  int32_t nCount = 0;
  if (bIsFindProperty) {
    for (CXFA_Node* child : parent->GetNodeList(XFA_NODEFILTER_Properties)) {
      if (bIsClassName) {
        if (child->GetClassHashCode() == dNameHash) {
          pSiblings->push_back(child);
          nCount++;
        }
      } else {
        if (child->GetNameHash() == dNameHash) {
          if (child->GetElementType() != XFA_Element::PageSet &&
              child->GetElementType() != XFA_Element::Extras &&
              child->GetElementType() != XFA_Element::Items) {
            pSiblings->push_back(child);
            nCount++;
          }
        }
      }
      if (child->IsUnnamed() &&
          child->GetElementType() == XFA_Element::PageSet) {
        nCount += NodeAcc_TraverseSiblings(child, dNameHash, pSiblings,
                                           eLogicType, bIsClassName, false);
      }
    }
    if (nCount > 0)
      return nCount;
  }
  for (CXFA_Node* child : parent->GetNodeList(XFA_NODEFILTER_Children)) {
    if (child->GetElementType() == XFA_Element::Variables)
      continue;

    if (bIsClassName) {
      if (child->GetClassHashCode() == dNameHash) {
        pSiblings->push_back(child);
        nCount++;
      }
    } else {
      if (child->GetNameHash() == dNameHash) {
        pSiblings->push_back(child);
        nCount++;
      }
    }
    if (eLogicType == XFA_LOGIC_NoTransparent)
      continue;

    if (NodeIsTransparent(child) &&
        child->GetElementType() != XFA_Element::PageSet) {
      nCount += NodeAcc_TraverseSiblings(child, dNameHash, pSiblings,
                                         eLogicType, bIsClassName, false);
    }
  }
  return nCount;
}

CXFA_Node* CXFA_NodeHelper::ResolveNodes_GetParent(CXFA_Node* pNode,
                                                   XFA_LOGIC_TYPE eLogicType) {
  if (!pNode) {
    return nullptr;
  }
  if (eLogicType == XFA_LOGIC_NoTransparent) {
    return pNode->GetNodeItem(XFA_NODEITEM_Parent);
  }
  CXFA_Node* parent;
  CXFA_Node* node = pNode;
  while (true) {
    parent = ResolveNodes_GetParent(node);
    if (!parent) {
      break;
    }
    XFA_Element parentType = parent->GetElementType();
    if ((!parent->IsUnnamed() && parentType != XFA_Element::SubformSet) ||
        parentType == XFA_Element::Variables) {
      break;
    }
    node = parent;
  }
  return parent;
}

int32_t CXFA_NodeHelper::GetIndex(CXFA_Node* pNode,
                                  XFA_LOGIC_TYPE eLogicType,
                                  bool bIsProperty,
                                  bool bIsClassIndex) {
  CXFA_Node* parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent);
  if (!parent) {
    return 0;
  }
  if (!bIsProperty && eLogicType == XFA_LOGIC_Transparent) {
    parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent);
    if (!parent) {
      return 0;
    }
  }
  uint32_t dwHashName = pNode->GetNameHash();
  if (bIsClassIndex) {
    dwHashName = pNode->GetClassHashCode();
  }
  std::vector<CXFA_Node*> siblings;
  int32_t iSize = NodeAcc_TraverseSiblings(parent, dwHashName, &siblings,
                                           eLogicType, bIsClassIndex);
  for (int32_t i = 0; i < iSize; ++i) {
    CXFA_Node* child = siblings[i];
    if (child == pNode) {
      return i;
    }
  }
  return 0;
}

void CXFA_NodeHelper::GetNameExpression(CXFA_Node* refNode,
                                        WideString& wsName,
                                        bool bIsAllPath,
                                        XFA_LOGIC_TYPE eLogicType) {
  wsName.clear();
  if (bIsAllPath) {
    GetNameExpression(refNode, wsName, false, eLogicType);
    WideString wsParent;
    CXFA_Node* parent =
        ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent);
    while (parent) {
      GetNameExpression(parent, wsParent, false, eLogicType);
      wsParent += L".";
      wsParent += wsName;
      wsName = wsParent;
      parent = ResolveNodes_GetParent(parent, XFA_LOGIC_NoTransparent);
    }
    return;
  }

  WideString ws;
  bool bIsProperty = NodeIsProperty(refNode);
  if (refNode->IsUnnamed() ||
      (bIsProperty && refNode->GetElementType() != XFA_Element::PageSet)) {
    ws = refNode->GetClassName();
    wsName.Format(L"#%s[%d]", ws.c_str(),
                  GetIndex(refNode, eLogicType, bIsProperty, true));
    return;
  }
  ws = refNode->GetCData(XFA_ATTRIBUTE_Name);
  ws.Replace(L".", L"\\.");
  wsName.Format(L"%s[%d]", ws.c_str(),
                GetIndex(refNode, eLogicType, bIsProperty, false));
}

bool CXFA_NodeHelper::NodeIsTransparent(CXFA_Node* refNode) {
  if (!refNode) {
    return false;
  }
  XFA_Element refNodeType = refNode->GetElementType();
  if ((refNode->IsUnnamed() && refNode->IsContainerNode()) ||
      refNodeType == XFA_Element::SubformSet ||
      refNodeType == XFA_Element::Area || refNodeType == XFA_Element::Proto) {
    return true;
  }
  return false;
}

bool CXFA_NodeHelper::CreateNode_ForCondition(WideString& wsCondition) {
  int32_t iLen = wsCondition.GetLength();
  WideString wsIndex(L"0");
  bool bAll = false;
  if (iLen == 0) {
    m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne;
    return false;
  }
  if (wsCondition[0] == '[') {
    int32_t i = 1;
    for (; i < iLen; ++i) {
      wchar_t ch = wsCondition[i];
      if (ch == ' ') {
        continue;
      }
      if (ch == '+' || ch == '-') {
        break;
      } else if (ch == '*') {
        bAll = true;
        break;
      } else {
        break;
      }
    }
    if (bAll) {
      wsIndex = L"1";
      m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeAll;
    } else {
      m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne;
      wsIndex = wsCondition.Mid(i, iLen - 1 - i);
    }
    int32_t iIndex = wsIndex.GetInteger();
    m_iCreateCount = iIndex;
    return true;
  }
  return false;
}

bool CXFA_NodeHelper::ResolveNodes_CreateNode(
    WideString wsName,
    WideString wsCondition,
    bool bLastNode,
    CXFA_ScriptContext* pScriptContext) {
  if (!m_pCreateParent) {
    return false;
  }
  bool bIsClassName = false;
  bool bResult = false;
  if (wsName[0] == '!') {
    wsName = wsName.Right(wsName.GetLength() - 1);
    m_pCreateParent = ToNode(
        pScriptContext->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets));
  }
  if (wsName[0] == '#') {
    bIsClassName = true;
    wsName = wsName.Right(wsName.GetLength() - 1);
  }
  if (m_iCreateCount == 0) {
    CreateNode_ForCondition(wsCondition);
  }
  if (bIsClassName) {
    XFA_Element eType = XFA_GetElementTypeForName(wsName.AsStringView());
    if (eType == XFA_Element::Unknown)
      return false;

    for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) {
      CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eType);
      if (pNewNode) {
        m_pCreateParent->InsertChild(pNewNode);
        if (iIndex == m_iCreateCount - 1) {
          m_pCreateParent = pNewNode;
        }
        bResult = true;
      }
    }
  } else {
    XFA_Element eClassType = XFA_Element::DataGroup;
    if (bLastNode) {
      eClassType = m_eLastCreateType;
    }
    for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) {
      CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eClassType);
      if (pNewNode) {
        pNewNode->SetAttribute(XFA_ATTRIBUTE_Name, wsName.AsStringView());
        pNewNode->CreateXMLMappingNode();
        m_pCreateParent->InsertChild(pNewNode);
        if (iIndex == m_iCreateCount - 1) {
          m_pCreateParent = pNewNode;
        }
        bResult = true;
      }
    }
  }
  if (!bResult) {
    m_pCreateParent = nullptr;
  }
  return bResult;
}

void CXFA_NodeHelper::SetCreateNodeType(CXFA_Node* refNode) {
  if (!refNode) {
    return;
  }
  if (refNode->GetElementType() == XFA_Element::Subform) {
    m_eLastCreateType = XFA_Element::DataGroup;
  } else if (refNode->GetElementType() == XFA_Element::Field) {
    m_eLastCreateType = XFA_FieldIsMultiListBox(refNode)
                            ? XFA_Element::DataGroup
                            : XFA_Element::DataValue;
  } else if (refNode->GetElementType() == XFA_Element::ExclGroup) {
    m_eLastCreateType = XFA_Element::DataValue;
  }
}

bool CXFA_NodeHelper::NodeIsProperty(CXFA_Node* refNode) {
  CXFA_Node* parent = ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent);
  return parent && refNode &&
         XFA_GetPropertyOfElement(parent->GetElementType(),
                                  refNode->GetElementType(),
                                  XFA_XDPPACKET_UNKNOWN);
}
