// 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/cxfa_ffdocview.h"

#include <set>
#include <utility>

#include "core/fxcrt/fx_extension.h"
#include "fxjs/gc/container_trace.h"
#include "fxjs/xfa/cfxjse_engine.h"
#include "fxjs/xfa/cjx_object.h"
#include "third_party/base/check_op.h"
#include "third_party/base/stl_util.h"
#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/cxfa_ffbarcode.h"
#include "xfa/fxfa/cxfa_ffcheckbutton.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/cxfa_ffexclgroup.h"
#include "xfa/fxfa/cxfa_fffield.h"
#include "xfa/fxfa/cxfa_ffimage.h"
#include "xfa/fxfa/cxfa_ffimageedit.h"
#include "xfa/fxfa/cxfa_ffpageview.h"
#include "xfa/fxfa/cxfa_ffpushbutton.h"
#include "xfa/fxfa/cxfa_ffsignature.h"
#include "xfa/fxfa/cxfa_fftext.h"
#include "xfa/fxfa/cxfa_ffwidget.h"
#include "xfa/fxfa/cxfa_ffwidgethandler.h"
#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
#include "xfa/fxfa/cxfa_readynodeiterator.h"
#include "xfa/fxfa/cxfa_textprovider.h"
#include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_acrobat.h"
#include "xfa/fxfa/parser/cxfa_binditems.h"
#include "xfa/fxfa/parser/cxfa_calculate.h"
#include "xfa/fxfa/parser/cxfa_pageset.h"
#include "xfa/fxfa/parser/cxfa_present.h"
#include "xfa/fxfa/parser/cxfa_subform.h"
#include "xfa/fxfa/parser/cxfa_validate.h"
#include "xfa/fxfa/parser/xfa_utils.h"

const XFA_AttributeValue gs_EventActivity[] = {
    XFA_AttributeValue::Click,      XFA_AttributeValue::Change,
    XFA_AttributeValue::DocClose,   XFA_AttributeValue::DocReady,
    XFA_AttributeValue::Enter,      XFA_AttributeValue::Exit,
    XFA_AttributeValue::Full,       XFA_AttributeValue::IndexChange,
    XFA_AttributeValue::Initialize, XFA_AttributeValue::MouseDown,
    XFA_AttributeValue::MouseEnter, XFA_AttributeValue::MouseExit,
    XFA_AttributeValue::MouseUp,    XFA_AttributeValue::PostExecute,
    XFA_AttributeValue::PostOpen,   XFA_AttributeValue::PostPrint,
    XFA_AttributeValue::PostSave,   XFA_AttributeValue::PostSign,
    XFA_AttributeValue::PostSubmit, XFA_AttributeValue::PreExecute,
    XFA_AttributeValue::PreOpen,    XFA_AttributeValue::PrePrint,
    XFA_AttributeValue::PreSave,    XFA_AttributeValue::PreSign,
    XFA_AttributeValue::PreSubmit,  XFA_AttributeValue::Ready,
    XFA_AttributeValue::Unknown,
};

CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {}

CXFA_FFDocView::~CXFA_FFDocView() = default;

void CXFA_FFDocView::Trace(cppgc::Visitor* visitor) const {
  visitor->Trace(m_pDoc);
  visitor->Trace(m_pWidgetHandler);
  visitor->Trace(m_pFocusNode);
  visitor->Trace(m_pFocusWidget);
  ContainerTrace(visitor, m_ValidateNodes);
  ContainerTrace(visitor, m_CalculateNodes);
  ContainerTrace(visitor, m_NewAddedNodes);
  ContainerTrace(visitor, m_BindItems);
  ContainerTrace(visitor, m_IndexChangedSubforms);
}

void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) {
  RunBindItems();
  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true);
  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true);
}

int32_t CXFA_FFDocView::StartLayout() {
  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
  m_pDoc->GetXFADoc()->DoProtoMerge();
  m_pDoc->GetXFADoc()->DoDataMerge();

  int32_t iStatus = GetLayoutProcessor()->StartLayout();
  if (iStatus < 0)
    return iStatus;

  CXFA_Node* pRootItem =
      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
  if (!pRootItem)
    return iStatus;

  InitLayout(pRootItem);
  InitCalculate(pRootItem);
  InitValidate(pRootItem);

  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true);
  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
  return iStatus;
}

int32_t CXFA_FFDocView::DoLayout() {
  int32_t iStatus = GetLayoutProcessor()->DoLayout();
  if (iStatus != 100)
    return iStatus;

  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing;
  return iStatus;
}

void CXFA_FFDocView::StopLayout() {
  CXFA_Node* pRootItem =
      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
  if (!pRootItem)
    return;

  CXFA_Subform* pSubformNode =
      pRootItem->GetChild<CXFA_Subform>(0, XFA_Element::Subform, false);
  if (!pSubformNode)
    return;

  CXFA_PageSet* pPageSetNode =
      pSubformNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
  if (!pPageSetNode)
    return;

  RunCalculateWidgets();
  RunValidate();

  InitLayout(pPageSetNode);
  InitCalculate(pPageSetNode);
  InitValidate(pPageSetNode);

  ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true);
  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true);
  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true);

  RunCalculateWidgets();
  RunValidate();

  if (RunLayout())
    ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true);

  m_CalculateNodes.clear();
  if (m_pFocusNode && !m_pFocusWidget)
    SetFocusNode(m_pFocusNode);

  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End;
}

void CXFA_FFDocView::ShowNullTestMsg() {
  int32_t iCount = pdfium::CollectionSize<int32_t>(m_NullTestMsgArray);
  CXFA_FFApp* pApp = m_pDoc->GetApp();
  IXFA_AppProvider* pAppProvider = pApp->GetAppProvider();
  if (pAppProvider && iCount) {
    int32_t iRemain = iCount > 7 ? iCount - 7 : 0;
    iCount -= iRemain;
    WideString wsMsg;
    for (int32_t i = 0; i < iCount; i++)
      wsMsg += m_NullTestMsgArray[i] + L"\n";

    if (iRemain > 0) {
      wsMsg += L"\n" + WideString::Format(
                           L"Message limit exceeded. Remaining %d "
                           L"validation errors not reported.",
                           iRemain);
    }
    pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(),
                         static_cast<uint32_t>(AlertIcon::kStatus),
                         static_cast<uint32_t>(AlertButton::kOK));
  }
  m_NullTestMsgArray.clear();
}

void CXFA_FFDocView::UpdateDocView() {
  if (IsUpdateLocked())
    return;

  LockUpdate();
  while (!m_NewAddedNodes.empty()) {
    CXFA_Node* pNode = m_NewAddedNodes.front();
    m_NewAddedNodes.pop_front();
    InitCalculate(pNode);
    InitValidate(pNode);
    ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true);
  }

  RunSubformIndexChange();
  RunCalculateWidgets();
  RunValidate();

  ShowNullTestMsg();

  if (RunLayout() && m_bLayoutEvent)
    RunEventLayoutReady();

  m_bLayoutEvent = false;
  m_CalculateNodes.clear();
  UnlockUpdate();
}

void CXFA_FFDocView::UpdateUIDisplay(CXFA_Node* pNode, CXFA_FFWidget* pExcept) {
  CXFA_FFWidget* pWidget = GetWidgetForNode(pNode);
  CXFA_FFWidget* pNext = nullptr;
  for (; pWidget; pWidget = pNext) {
    pNext = pWidget->GetNextFFWidget();
    if (pWidget == pExcept || !pWidget->IsLoaded() ||
        (pNode->GetFFWidgetType() != XFA_FFWidgetType::kCheckButton &&
         pWidget->IsFocused())) {
      continue;
    }
    pWidget->UpdateFWLData();
    pWidget->InvalidateRect();
  }
}

int32_t CXFA_FFDocView::CountPageViews() const {
  CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor();
  return pProcessor ? pProcessor->CountPages() : 0;
}

CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) const {
  CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor();
  if (!pProcessor)
    return nullptr;

  auto* pPage = pProcessor->GetPage(nIndex);
  return pPage ? pPage->GetPageView() : nullptr;
}

CXFA_LayoutProcessor* CXFA_FFDocView::GetLayoutProcessor() const {
  return CXFA_LayoutProcessor::FromDocument(m_pDoc->GetXFADoc());
}

bool CXFA_FFDocView::ResetSingleNodeData(CXFA_Node* pNode) {
  XFA_Element eType = pNode->GetElementType();
  if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
    return false;

  pNode->ResetData();
  UpdateUIDisplay(pNode, nullptr);
  CXFA_Validate* validate = pNode->GetValidateIfExists();
  if (!validate)
    return true;

  AddValidateNode(pNode);
  validate->SetFlag(XFA_NodeFlag_NeedsInitApp);
  return true;
}

void CXFA_FFDocView::ResetNode(CXFA_Node* pNode) {
  m_bLayoutEvent = true;
  bool bChanged = false;
  CXFA_Node* pFormNode = nullptr;
  if (pNode) {
    bChanged = ResetSingleNodeData(pNode);
    pFormNode = pNode;
  } else {
    pFormNode = GetRootSubform();
  }
  if (!pFormNode)
    return;

  if (pFormNode->GetElementType() != XFA_Element::Field &&
      pFormNode->GetElementType() != XFA_Element::ExclGroup) {
    CXFA_ReadyNodeIterator it(pFormNode);
    while (CXFA_Node* next_node = it.MoveToNext()) {
      bChanged |= ResetSingleNodeData(next_node);
      if (next_node->GetElementType() == XFA_Element::ExclGroup)
        it.SkipTree();
    }
  }
  if (bChanged)
    m_pDoc->SetChangeMark();
}

CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) {
  return GetFFWidget(
      ToContentLayoutItem(GetLayoutProcessor()->GetLayoutItem(node)));
}

CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() {
  if (!m_pWidgetHandler) {
    m_pWidgetHandler = cppgc::MakeGarbageCollected<CXFA_FFWidgetHandler>(
        m_pDoc->GetHeap()->GetAllocationHandle(), this);
  }
  return m_pWidgetHandler;
}

bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* pNewFocus) {
  if (pNewFocus == m_pFocusWidget)
    return false;

  if (m_pFocusWidget) {
    CXFA_ContentLayoutItem* pItem = m_pFocusWidget->GetLayoutItem();
    if (pItem->TestStatusBits(XFA_WidgetStatus_Visible) &&
        !pItem->TestStatusBits(XFA_WidgetStatus_Focused)) {
      if (!m_pFocusWidget->IsLoaded())
        m_pFocusWidget->LoadWidget();
      if (!m_pFocusWidget->OnSetFocus(m_pFocusWidget))
        m_pFocusWidget.Clear();
    }
  }
  if (m_pFocusWidget) {
    if (!m_pFocusWidget->OnKillFocus(pNewFocus))
      return false;
  }

  if (pNewFocus) {
    if (pNewFocus->GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Visible)) {
      if (!pNewFocus->IsLoaded())
        pNewFocus->LoadWidget();
      if (!pNewFocus->OnSetFocus(m_pFocusWidget))
        pNewFocus = nullptr;
    }
  }
  if (pNewFocus) {
    CXFA_Node* node = pNewFocus->GetNode();
    m_pFocusNode = node->IsWidgetReady() ? node : nullptr;
    m_pFocusWidget = pNewFocus;
  } else {
    m_pFocusNode.Clear();
    m_pFocusWidget.Clear();
  }
  return true;
}

void CXFA_FFDocView::SetFocusNode(CXFA_Node* node) {
  CXFA_FFWidget* pNewFocus = node ? GetWidgetForNode(node) : nullptr;
  if (!SetFocus(pNewFocus))
    return;

  m_pFocusNode = node;
  if (m_iStatus != XFA_DOCVIEW_LAYOUTSTATUS_End)
    return;

  m_pDoc->SetFocusWidget(m_pFocusWidget);
}

void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) {
  if (m_pFocusNode != pWidget->GetNode())
    return;

  m_pFocusNode.Clear();
  m_pFocusWidget.Clear();
}

static XFA_EventError XFA_ProcessEvent(CXFA_FFDocView* pDocView,
                                       CXFA_Node* pNode,
                                       CXFA_EventParam* pParam) {
  if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
    return XFA_EventError::kNotExist;
  if (pNode && pNode->GetElementType() == XFA_Element::Draw)
    return XFA_EventError::kNotExist;

  switch (pParam->m_eType) {
    case XFA_EVENT_Calculate:
      return pNode->ProcessCalculate(pDocView);
    case XFA_EVENT_Validate:
      if (pDocView->GetDoc()->IsValidationsEnabled())
        return pNode->ProcessValidate(pDocView, 0x01);
      return XFA_EventError::kDisabled;
    case XFA_EVENT_InitCalculate: {
      CXFA_Calculate* calc = pNode->GetCalculateIfExists();
      if (!calc)
        return XFA_EventError::kNotExist;
      if (pNode->IsUserInteractive())
        return XFA_EventError::kDisabled;
      return pNode->ExecuteScript(pDocView, calc->GetScriptIfExists(), pParam);
    }
    default:
      return pNode->ProcessEvent(pDocView, gs_EventActivity[pParam->m_eType],
                                 pParam);
  }
}

XFA_EventError CXFA_FFDocView::ExecEventActivityByDeepFirst(
    CXFA_Node* pFormNode,
    XFA_EVENTTYPE eEventType,
    bool bIsFormReady,
    bool bRecursive) {
  if (!pFormNode)
    return XFA_EventError::kNotExist;

  XFA_Element elementType = pFormNode->GetElementType();
  if (elementType == XFA_Element::Field) {
    if (eEventType == XFA_EVENT_IndexChange)
      return XFA_EventError::kNotExist;

    if (!pFormNode->IsWidgetReady())
      return XFA_EventError::kNotExist;

    CXFA_EventParam eParam;
    eParam.m_eType = eEventType;
    eParam.m_pTarget = pFormNode;
    eParam.m_bIsFormReady = bIsFormReady;
    return XFA_ProcessEvent(this, pFormNode, &eParam);
  }

  XFA_EventError iRet = XFA_EventError::kNotExist;
  if (bRecursive) {
    for (CXFA_Node* pNode = pFormNode->GetFirstContainerChild(); pNode;
         pNode = pNode->GetNextContainerSibling()) {
      elementType = pNode->GetElementType();
      if (elementType != XFA_Element::Variables &&
          elementType != XFA_Element::Draw) {
        XFA_EventErrorAccumulate(
            &iRet, ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady,
                                                bRecursive));
      }
    }
  }
  if (!pFormNode->IsWidgetReady())
    return iRet;

  CXFA_EventParam eParam;
  eParam.m_eType = eEventType;
  eParam.m_pTarget = pFormNode;
  eParam.m_bIsFormReady = bIsFormReady;

  XFA_EventErrorAccumulate(&iRet, XFA_ProcessEvent(this, pFormNode, &eParam));
  return iRet;
}

CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const WideString& wsName,
                                               CXFA_FFWidget* pRefWidget) {
  CFXJSE_Engine* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext();
  CXFA_Node* pRefNode = nullptr;
  if (pRefWidget) {
    CXFA_Node* node = pRefWidget->GetNode();
    pRefNode = node->IsWidgetReady() ? node : nullptr;
  }
  WideString wsExpression = (!pRefNode ? L"$form." : L"") + wsName;
  constexpr XFA_ResolveNodeMask kFlags =
      XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
      XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
  Optional<CFXJSE_Engine::ResolveResult> maybeResult =
      pScriptContext->ResolveObjects(pRefNode, wsExpression.AsStringView(),
                                     kFlags);
  if (!maybeResult.has_value())
    return nullptr;

  if (maybeResult.value().type == CFXJSE_Engine::ResolveResult::Type::kNodes) {
    CXFA_Node* pNode = maybeResult.value().objects.front()->AsNode();
    if (pNode && pNode->IsWidgetReady())
      return GetWidgetForNode(pNode);
  }
  return nullptr;
}

void CXFA_FFDocView::OnPageViewEvent(
    CXFA_ViewLayoutItem* pSender,
    IXFA_DocEnvironment::PageViewEvent eEvent) {
  CXFA_FFPageView* pFFPageView = pSender ? pSender->GetPageView() : nullptr;
  m_pDoc->OnPageViewEvent(pFFPageView, eEvent);
}

void CXFA_FFDocView::InvalidateRect(CXFA_FFPageView* pPageView,
                                    const CFX_RectF& rtInvalidate) {
  m_pDoc->InvalidateRect(pPageView, rtInvalidate);
}

bool CXFA_FFDocView::RunLayout() {
  LockUpdate();
  m_bInLayoutStatus = true;

  CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor();
  if (!pProcessor->IncrementLayout() && pProcessor->StartLayout() < 100) {
    pProcessor->DoLayout();
    UnlockUpdate();
    m_bInLayoutStatus = false;
    m_pDoc->OnPageViewEvent(nullptr,
                            IXFA_DocEnvironment::PageViewEvent::kStopLayout);
    return true;
  }

  m_bInLayoutStatus = false;
  m_pDoc->OnPageViewEvent(nullptr,
                          IXFA_DocEnvironment::PageViewEvent::kStopLayout);
  UnlockUpdate();
  return false;
}

void CXFA_FFDocView::RunSubformIndexChange() {
  std::set<CXFA_Node*> seen;
  while (!m_IndexChangedSubforms.empty()) {
    CXFA_Node* pSubformNode = m_IndexChangedSubforms.front();
    m_IndexChangedSubforms.pop_front();
    bool bInserted = seen.insert(pSubformNode).second;
    if (!bInserted || !pSubformNode->IsWidgetReady())
      continue;

    CXFA_EventParam eParam;
    eParam.m_eType = XFA_EVENT_IndexChange;
    eParam.m_pTarget = pSubformNode;
    pSubformNode->ProcessEvent(this, XFA_AttributeValue::IndexChange, &eParam);
  }
}

void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) {
  m_NewAddedNodes.push_back(pNode);
  InitLayout(pNode);
}

void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) {
  DCHECK_EQ(pNode->GetElementType(), XFA_Element::Subform);
  if (!pdfium::Contains(m_IndexChangedSubforms, pNode))
    m_IndexChangedSubforms.push_back(pNode);
}

void CXFA_FFDocView::RunDocClose() {
  CXFA_Node* pRootItem =
      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
  if (!pRootItem)
    return;

  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true);
}

void CXFA_FFDocView::AddCalculateNode(CXFA_Node* node) {
  CXFA_Node* pCurrentNode =
      !m_CalculateNodes.empty() ? m_CalculateNodes.back() : nullptr;
  if (pCurrentNode != node)
    m_CalculateNodes.push_back(node);
}

void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) {
  CJX_Object::CalcData* pGlobalData = pNodeChange->JSObject()->GetCalcData();
  if (!pGlobalData)
    return;

  for (auto pResult : pGlobalData->m_Globals) {
    if (!pResult->HasRemovedChildren() && pResult->IsWidgetReady())
      AddCalculateNode(pResult);
  }
}

size_t CXFA_FFDocView::RunCalculateRecursive(size_t index) {
  while (index < m_CalculateNodes.size()) {
    CXFA_Node* node = m_CalculateNodes[index];

    AddCalculateNodeNotify(node);
    size_t recurse = node->JSObject()->GetCalcRecursionCount() + 1;
    node->JSObject()->SetCalcRecursionCount(recurse);
    if (recurse > 11)
      break;
    if (node->ProcessCalculate(this) == XFA_EventError::kSuccess &&
        node->IsWidgetReady()) {
      AddValidateNode(node);
    }

    index = RunCalculateRecursive(++index);
  }
  return index;
}

XFA_EventError CXFA_FFDocView::RunCalculateWidgets() {
  if (!m_pDoc->IsCalculationsEnabled())
    return XFA_EventError::kDisabled;

  if (!m_CalculateNodes.empty())
    RunCalculateRecursive(0);

  for (CXFA_Node* node : m_CalculateNodes)
    node->JSObject()->SetCalcRecursionCount(0);

  m_CalculateNodes.clear();
  return XFA_EventError::kSuccess;
}

void CXFA_FFDocView::AddValidateNode(CXFA_Node* node) {
  if (!pdfium::Contains(m_ValidateNodes, node))
    m_ValidateNodes.push_back(node);
}

void CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) {
  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true);
}

void CXFA_FFDocView::ProcessValueChanged(CXFA_Node* node) {
  AddValidateNode(node);
  AddCalculateNode(node);
  RunCalculateWidgets();
  RunValidate();
}

bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) {
  if (!m_pDoc->IsValidationsEnabled())
    return false;

  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true);
  m_ValidateNodes.clear();
  return true;
}

bool CXFA_FFDocView::RunValidate() {
  if (!m_pDoc->IsValidationsEnabled())
    return false;

  while (!m_ValidateNodes.empty()) {
    CXFA_Node* node = m_ValidateNodes.front();
    m_ValidateNodes.pop_front();
    if (!node->HasRemovedChildren())
      node->ProcessValidate(this, 0);
  }
  return true;
}

bool CXFA_FFDocView::RunEventLayoutReady() {
  CXFA_Node* pRootItem =
      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
  if (!pRootItem)
    return false;

  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true);
  RunLayout();
  return true;
}

void CXFA_FFDocView::RunBindItems() {
  while (!m_BindItems.empty()) {
    CXFA_BindItems* item = m_BindItems.front();
    m_BindItems.pop_front();
    if (item->HasRemovedChildren())
      continue;

    CXFA_Node* pWidgetNode = item->GetParent();
    if (!pWidgetNode || !pWidgetNode->IsWidgetReady())
      continue;

    CFXJSE_Engine* pScriptContext =
        pWidgetNode->GetDocument()->GetScriptContext();
    WideString wsRef = item->GetRef();
    constexpr XFA_ResolveNodeMask kFlags =
        XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
        XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_ALL;
    Optional<CFXJSE_Engine::ResolveResult> maybeRS =
        pScriptContext->ResolveObjects(pWidgetNode, wsRef.AsStringView(),
                                       kFlags);
    pWidgetNode->DeleteItem(-1, false, false);
    if (!maybeRS.has_value() ||
        maybeRS.value().type != CFXJSE_Engine::ResolveResult::Type::kNodes ||
        maybeRS.value().objects.empty()) {
      continue;
    }
    WideString wsValueRef = item->GetValueRef();
    WideString wsLabelRef = item->GetLabelRef();
    const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef;
    const bool bLabelUseContent =
        wsLabelRef.IsEmpty() || wsLabelRef.EqualsASCII("$");
    const bool bValueUseContent =
        wsValueRef.IsEmpty() || wsValueRef.EqualsASCII("$");
    WideString wsValue;
    WideString wsLabel;
    uint32_t uValueHash = FX_HashCode_GetW(wsValueRef.AsStringView());
    for (auto& refObject : maybeRS.value().objects) {
      CXFA_Node* refNode = refObject->AsNode();
      if (!refNode)
        continue;

      if (bValueUseContent) {
        wsValue = refNode->JSObject()->GetContent(false);
      } else {
        CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash);
        wsValue = nodeValue ? nodeValue->JSObject()->GetContent(false)
                            : refNode->JSObject()->GetContent(false);
      }

      if (!bUseValue) {
        if (bLabelUseContent) {
          wsLabel = refNode->JSObject()->GetContent(false);
        } else {
          CXFA_Node* nodeLabel =
              refNode->GetFirstChildByName(wsLabelRef.AsStringView());
          if (nodeLabel)
            wsLabel = nodeLabel->JSObject()->GetContent(false);
        }
      } else {
        wsLabel = wsValue;
      }
      pWidgetNode->InsertItem(wsLabel, wsValue, false);
    }
  }
}

void CXFA_FFDocView::SetChangeMark() {
  if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End)
    return;

  m_pDoc->SetChangeMark();
}

CXFA_Node* CXFA_FFDocView::GetRootSubform() {
  CXFA_Node* pFormPacketNode =
      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
  if (!pFormPacketNode)
    return nullptr;

  return pFormPacketNode->GetFirstChildByClass<CXFA_Subform>(
      XFA_Element::Subform);
}
