// Copyright 2014 The PDFium Authors
// 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 "core/fxcrt/stl_util.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/containers/contains.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 kXFAEventActivity[] = {
    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::UpdateScope::UpdateScope(CXFA_FFDocView* pDocView)
    : m_pDocView(pDocView) {
  m_pDocView->LockUpdate();
}

CXFA_FFDocView::UpdateScope::~UpdateScope() {
  m_pDocView->UnlockUpdate();
  m_pDocView->UpdateDocView();
}

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 = LayoutStatus::kStart;
  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 = LayoutStatus::kStart;
  return iStatus;
}

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

  m_iStatus = LayoutStatus::kDoing;
  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 = LayoutStatus::kEnd;
}

void CXFA_FFDocView::AddNullTestMsg(const WideString& msg) {
  m_NullTestMsgArray.push_back(msg);
}

void CXFA_FFDocView::ShowNullTestMsg() {
  int32_t iCount = fxcrt::CollectionSize<int32_t>(m_NullTestMsgArray);
  CXFA_FFApp* pApp = m_pDoc->GetApp();
  CXFA_FFApp::CallbackIface* 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::kNeedsInitApp);
  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::kVisible) &&
        !pItem->TestStatusBits(XFA_WidgetStatus::kFocused)) {
      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::kVisible)) {
      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 != LayoutStatus::kEnd)
    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, kXFAEventActivity[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;
  absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
      pScriptContext->ResolveObjects(
          pRefNode, wsExpression.AsStringView(),
          Mask<XFA_ResolveFlag>{
              XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kProperties,
              XFA_ResolveFlag::kSiblings, XFA_ResolveFlag::kParent});
  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,
                                     CXFA_FFDoc::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, CXFA_FFDoc::PageViewEvent::kStopLayout);
    return true;
  }

  m_bInLayoutStatus = false;
  m_pDoc->OnPageViewEvent(nullptr, CXFA_FFDoc::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_Subform* pNode) {
  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();
    absl::optional<CFXJSE_Engine::ResolveResult> maybeRS =
        pScriptContext->ResolveObjects(
            pWidgetNode, wsRef.AsStringView(),
            Mask<XFA_ResolveFlag>{
                XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kProperties,
                XFA_ResolveFlag::kSiblings, XFA_ResolveFlag::kParent,
                XFA_ResolveFlag::kALL});
    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 != LayoutStatus::kEnd)
    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);
}
