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

#include <memory>
#include <utility>

#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/cxfa_ffarc.h"
#include "xfa/fxfa/cxfa_ffbarcode.h"
#include "xfa/fxfa/cxfa_ffcheckbutton.h"
#include "xfa/fxfa/cxfa_ffcombobox.h"
#include "xfa/fxfa/cxfa_ffdatetimeedit.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/cxfa_ffdocview.h"
#include "xfa/fxfa/cxfa_ffdraw.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_ffline.h"
#include "xfa/fxfa/cxfa_fflistbox.h"
#include "xfa/fxfa/cxfa_ffnumericedit.h"
#include "xfa/fxfa/cxfa_ffpageview.h"
#include "xfa/fxfa/cxfa_ffpasswordedit.h"
#include "xfa/fxfa/cxfa_ffpushbutton.h"
#include "xfa/fxfa/cxfa_ffrectangle.h"
#include "xfa/fxfa/cxfa_ffsignature.h"
#include "xfa/fxfa/cxfa_ffsubform.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_textlayout.h"
#include "xfa/fxfa/cxfa_textprovider.h"
#include "xfa/fxfa/parser/cxfa_binditems.h"
#include "xfa/fxfa/parser/cxfa_node.h"

namespace {

CXFA_FFListBox* ToListBox(CXFA_FFWidget* widget) {
  return static_cast<CXFA_FFListBox*>(widget);
}

CXFA_FFComboBox* ToComboBox(CXFA_FFWidget* widget) {
  return static_cast<CXFA_FFComboBox*>(widget);
}

}  // namespace

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

CXFA_FFNotify::~CXFA_FFNotify() {}

void CXFA_FFNotify::OnPageEvent(CXFA_ContainerLayoutItem* pSender,
                                uint32_t dwEvent) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pSender->GetLayout());
  if (pDocView)
    pDocView->OnPageEvent(pSender, dwEvent);
}

void CXFA_FFNotify::OnWidgetListItemAdded(CXFA_Node* pSender,
                                          const wchar_t* pLabel,
                                          const wchar_t* pValue,
                                          int32_t iIndex) {
  if (pSender->GetUIType() != XFA_Element::ChoiceList)
    return;

  CXFA_FFWidget* pWidget = m_pDoc->GetDocView()->GetWidgetForNode(pSender);
  for (; pWidget; pWidget = pSender->GetWidgetAcc()->GetNextWidget(pWidget)) {
    if (pWidget->IsLoaded()) {
      if (pSender->GetWidgetAcc()->IsListBox())
        ToListBox(pWidget)->InsertItem(pLabel, iIndex);
      else
        ToComboBox(pWidget)->InsertItem(pLabel, iIndex);
    }
  }
}

void CXFA_FFNotify::OnWidgetListItemRemoved(CXFA_Node* pSender,
                                            int32_t iIndex) {
  if (pSender->GetUIType() != XFA_Element::ChoiceList)
    return;

  CXFA_FFWidget* pWidget = m_pDoc->GetDocView()->GetWidgetForNode(pSender);
  for (; pWidget; pWidget = pSender->GetWidgetAcc()->GetNextWidget(pWidget)) {
    if (pWidget->IsLoaded()) {
      if (pSender->GetWidgetAcc()->IsListBox())
        ToListBox(pWidget)->DeleteItem(iIndex);
      else
        ToComboBox(pWidget)->DeleteItem(iIndex);
    }
  }
}

CXFA_ContainerLayoutItem* CXFA_FFNotify::OnCreateContainerLayoutItem(
    CXFA_Node* pNode) {
  XFA_Element type = pNode->GetElementType();
  ASSERT(type == XFA_Element::ContentArea || type == XFA_Element::PageArea);

  if (type == XFA_Element::PageArea) {
    CXFA_LayoutProcessor* pLayout = m_pDoc->GetXFADoc()->GetDocLayout();
    return new CXFA_FFPageView(m_pDoc->GetDocView(pLayout), pNode);
  }
  return new CXFA_ContainerLayoutItem(pNode);
}

CXFA_ContentLayoutItem* CXFA_FFNotify::OnCreateContentLayoutItem(
    CXFA_Node* pNode) {
  ASSERT(pNode->GetElementType() != XFA_Element::ContentArea);
  ASSERT(pNode->GetElementType() != XFA_Element::PageArea);

  // We only need to create the widget for certain types of objects.
  if (!pNode->HasCreatedUIWidget())
    return new CXFA_ContentLayoutItem(pNode);

  CXFA_FFWidget* pWidget;
  switch (pNode->GetUIType()) {
    case XFA_Element::Barcode:
      pWidget = new CXFA_FFBarcode(pNode);
      break;
    case XFA_Element::Button:
      pWidget = new CXFA_FFPushButton(pNode);
      break;
    case XFA_Element::CheckButton:
      pWidget = new CXFA_FFCheckButton(pNode);
      break;
    case XFA_Element::ChoiceList: {
      if (pNode->GetWidgetAcc()->IsListBox())
        pWidget = new CXFA_FFListBox(pNode);
      else
        pWidget = new CXFA_FFComboBox(pNode);
    } break;
    case XFA_Element::DateTimeEdit:
      pWidget = new CXFA_FFDateTimeEdit(pNode);
      break;
    case XFA_Element::ImageEdit:
      pWidget = new CXFA_FFImageEdit(pNode);
      break;
    case XFA_Element::NumericEdit:
      pWidget = new CXFA_FFNumericEdit(pNode);
      break;
    case XFA_Element::PasswordEdit:
      pWidget = new CXFA_FFPasswordEdit(pNode);
      break;
    case XFA_Element::Signature:
      pWidget = new CXFA_FFSignature(pNode);
      break;
    case XFA_Element::TextEdit:
      pWidget = new CXFA_FFTextEdit(pNode);
      break;
    case XFA_Element::Arc:
      pWidget = new CXFA_FFArc(pNode);
      break;
    case XFA_Element::Line:
      pWidget = new CXFA_FFLine(pNode);
      break;
    case XFA_Element::Rectangle:
      pWidget = new CXFA_FFRectangle(pNode);
      break;
    case XFA_Element::Text:
      pWidget = new CXFA_FFText(pNode);
      break;
    case XFA_Element::Image:
      pWidget = new CXFA_FFImage(pNode);
      break;
    case XFA_Element::Draw:
      pWidget = new CXFA_FFDraw(pNode);
      break;
    case XFA_Element::Subform:
      pWidget = new CXFA_FFSubForm(pNode);
      break;
    case XFA_Element::ExclGroup:
      pWidget = new CXFA_FFExclGroup(pNode);
      break;
    case XFA_Element::DefaultUi:
    default:
      pWidget = nullptr;
      break;
  }

  if (pWidget) {
    CXFA_LayoutProcessor* pLayout = m_pDoc->GetXFADoc()->GetDocLayout();
    pWidget->SetDocView(m_pDoc->GetDocView(pLayout));
  }
  return pWidget;
}

void CXFA_FFNotify::StartFieldDrawLayout(CXFA_Node* pItem,
                                         float& fCalcWidth,
                                         float& fCalcHeight) {
  if (!pItem->GetWidgetAcc())
    return;

  pItem->GetWidgetAcc()->StartWidgetLayout(m_pDoc.Get(), fCalcWidth,
                                           fCalcHeight);
}

bool CXFA_FFNotify::FindSplitPos(CXFA_Node* pItem,
                                 int32_t iBlockIndex,
                                 float& fCalcHeightPos) {
  return pItem->GetWidgetAcc() &&
         pItem->GetWidgetAcc()->FindSplitPos(m_pDoc->GetDocView(), iBlockIndex,
                                             fCalcHeightPos);
}

bool CXFA_FFNotify::RunScript(CXFA_Script* script, CXFA_Node* item) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return false;

  CXFA_EventParam EventParam;
  EventParam.m_eType = XFA_EVENT_Unknown;

  int32_t iRet;
  bool bRet;
  std::tie(iRet, bRet) = item->ExecuteBoolScript(pDocView, script, &EventParam);
  return iRet == XFA_EVENTERROR_Success && bRet;
}

int32_t CXFA_FFNotify::ExecEventByDeepFirst(CXFA_Node* pFormNode,
                                            XFA_EVENTTYPE eEventType,
                                            bool bIsFormReady,
                                            bool bRecursive) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return XFA_EVENTERROR_NotExist;
  return pDocView->ExecEventActivityByDeepFirst(pFormNode, eEventType,
                                                bIsFormReady, bRecursive);
}

void CXFA_FFNotify::AddCalcValidate(CXFA_Node* pNode) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;
  if (!pNode->GetWidgetAcc())
    return;

  pDocView->AddCalculateNode(pNode);
  pDocView->AddValidateNode(pNode);
}

CXFA_FFDoc* CXFA_FFNotify::GetHDOC() {
  return m_pDoc.Get();
}

IXFA_DocEnvironment* CXFA_FFNotify::GetDocEnvironment() const {
  return m_pDoc->GetDocEnvironment();
}

IXFA_AppProvider* CXFA_FFNotify::GetAppProvider() {
  return m_pDoc->GetApp()->GetAppProvider();
}

CXFA_FFWidgetHandler* CXFA_FFNotify::GetWidgetHandler() {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  return pDocView ? pDocView->GetWidgetHandler() : nullptr;
}

CXFA_FFWidget* CXFA_FFNotify::GetHWidget(CXFA_LayoutItem* pLayoutItem) {
  return XFA_GetWidgetFromLayoutItem(pLayoutItem);
}

void CXFA_FFNotify::OpenDropDownList(CXFA_FFWidget* hWidget) {
  if (hWidget->GetNode()->GetUIType() != XFA_Element::ChoiceList)
    return;

  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  pDocView->LockUpdate();
  ToComboBox(hWidget)->OpenDropDownList();
  pDocView->UnlockUpdate();
  pDocView->UpdateDocView();
}

WideString CXFA_FFNotify::GetCurrentDateTime() {
  CFX_DateTime dataTime = CFX_DateTime::Now();
  return WideString::Format(L"%d%02d%02dT%02d%02d%02d", dataTime.GetYear(),
                            dataTime.GetMonth(), dataTime.GetDay(),
                            dataTime.GetHour(), dataTime.GetMinute(),
                            dataTime.GetSecond());
}

void CXFA_FFNotify::ResetData(CXFA_Node* pNode) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;

  pDocView->ResetNode(pNode);
}

int32_t CXFA_FFNotify::GetLayoutStatus() {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  return pDocView ? pDocView->GetLayoutStatus() : 0;
}

void CXFA_FFNotify::RunNodeInitialize(CXFA_Node* pNode) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;

  pDocView->AddNewFormNode(pNode);
}

void CXFA_FFNotify::RunSubformIndexChange(CXFA_Node* pSubformNode) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;

  pDocView->AddIndexChangedSubform(pSubformNode);
}

CXFA_Node* CXFA_FFNotify::GetFocusWidgetNode() {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  return pDocView ? pDocView->GetFocusNode() : nullptr;
}

void CXFA_FFNotify::SetFocusWidgetNode(CXFA_Node* pNode) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;
  pDocView->SetFocusNode(pNode);
}

void CXFA_FFNotify::OnNodeReady(CXFA_Node* pNode) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;

  if (pNode->HasCreatedUIWidget()) {
    pNode->SetWidgetReady();
    return;
  }

  switch (pNode->GetElementType()) {
    case XFA_Element::BindItems:
      pDocView->AddBindItem(static_cast<CXFA_BindItems*>(pNode));
      break;
    case XFA_Element::Validate:
      pNode->SetFlag(XFA_NodeFlag_NeedsInitApp, false);
      break;
    default:
      break;
  }
}

void CXFA_FFNotify::OnValueChanging(CXFA_Node* pSender, XFA_Attribute eAttr) {
  if (eAttr != XFA_Attribute::Presence)
    return;
  if (pSender->GetPacketType() == XFA_PacketType::Datasets)
    return;
  if (!pSender->IsFormContainer())
    return;

  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;
  if (pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End)
    return;
  if (!pSender->GetWidgetAcc())
    return;

  CXFA_FFWidget* pWidget = m_pDoc->GetDocView()->GetWidgetForNode(pSender);
  for (; pWidget; pWidget = pSender->GetWidgetAcc()->GetNextWidget(pWidget)) {
    if (pWidget->IsLoaded())
      pWidget->AddInvalidateRect();
  }
}

void CXFA_FFNotify::OnValueChanged(CXFA_Node* pSender,
                                   XFA_Attribute eAttr,
                                   CXFA_Node* pParentNode,
                                   CXFA_Node* pWidgetNode) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;

  if (pSender->GetPacketType() != XFA_PacketType::Form) {
    if (eAttr == XFA_Attribute::Value)
      pDocView->AddCalculateNodeNotify(pSender);
    return;
  }

  XFA_Element eType = pParentNode->GetElementType();
  bool bIsContainerNode = pParentNode->IsContainerNode();
  if (!pWidgetNode->GetWidgetAcc())
    return;

  bool bUpdateProperty = false;
  pDocView->SetChangeMark();
  switch (eType) {
    case XFA_Element::Caption: {
      CXFA_TextLayout* pCapOut =
          pWidgetNode->GetWidgetAcc()->GetCaptionTextLayout();
      if (!pCapOut)
        return;

      pCapOut->Unload();
      break;
    }
    case XFA_Element::Ui:
    case XFA_Element::Para:
      bUpdateProperty = true;
      break;
    default:
      break;
  }
  if (bIsContainerNode && eAttr == XFA_Attribute::Access)
    bUpdateProperty = true;

  if (eAttr == XFA_Attribute::Value) {
    pDocView->AddCalculateNodeNotify(pSender);
    if (eType == XFA_Element::Value || bIsContainerNode) {
      if (bIsContainerNode) {
        pWidgetNode->GetWidgetAcc()->UpdateUIDisplay(m_pDoc->GetDocView(),
                                                     nullptr);
        pDocView->AddCalculateNode(pWidgetNode);
        pDocView->AddValidateNode(pWidgetNode);
      } else if (pWidgetNode->GetParent()->GetElementType() ==
                 XFA_Element::ExclGroup) {
        pWidgetNode->GetWidgetAcc()->UpdateUIDisplay(m_pDoc->GetDocView(),
                                                     nullptr);
      }
      return;
    }
  }

  CXFA_FFWidget* pWidget = m_pDoc->GetDocView()->GetWidgetForNode(pWidgetNode);
  for (; pWidget;
       pWidget = pWidgetNode->GetWidgetAcc()->GetNextWidget(pWidget)) {
    if (!pWidget->IsLoaded())
      continue;

    if (bUpdateProperty)
      pWidget->UpdateWidgetProperty();
    pWidget->PerformLayout();
    pWidget->AddInvalidateRect();
  }
}

void CXFA_FFNotify::OnChildAdded(CXFA_Node* pSender) {
  if (!pSender->IsFormContainer())
    return;

  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;

  bool bLayoutReady =
      !(pDocView->m_bInLayoutStatus) &&
      (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End);
  if (bLayoutReady)
    m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get());
}

void CXFA_FFNotify::OnChildRemoved() {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
  if (!pDocView)
    return;

  bool bLayoutReady =
      !(pDocView->m_bInLayoutStatus) &&
      (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End);
  if (bLayoutReady)
    m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get());
}

void CXFA_FFNotify::OnLayoutItemAdded(CXFA_LayoutProcessor* pLayout,
                                      CXFA_LayoutItem* pSender,
                                      int32_t iPageIdx,
                                      uint32_t dwStatus) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
  if (!pDocView)
    return;

  CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender);
  if (!pWidget)
    return;

  CXFA_FFPageView* pNewPageView = pDocView->GetPageView(iPageIdx);
  uint32_t dwFilter = XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable |
                      XFA_WidgetStatus_Printable;
  pWidget->ModifyStatus(dwStatus, dwFilter);
  CXFA_FFPageView* pPrePageView = pWidget->GetPageView();
  if (pPrePageView != pNewPageView ||
      (dwStatus & (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)) ==
          (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)) {
    pWidget->SetPageView(pNewPageView);
    m_pDoc->GetDocEnvironment()->WidgetPostAdd(pWidget);
  }
  if (pDocView->GetLayoutStatus() != XFA_DOCVIEW_LAYOUTSTATUS_End ||
      !(dwStatus & XFA_WidgetStatus_Visible)) {
    return;
  }
  if (pWidget->IsLoaded()) {
    if (pWidget->GetWidgetRect() != pWidget->RecacheWidgetRect())
      pWidget->PerformLayout();
  } else {
    pWidget->LoadWidget();
  }
  pWidget->AddInvalidateRect();
}

void CXFA_FFNotify::OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout,
                                         CXFA_LayoutItem* pSender) {
  CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
  if (!pDocView)
    return;

  CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender);
  if (!pWidget)
    return;

  pDocView->DeleteLayoutItem(pWidget);
  m_pDoc->GetDocEnvironment()->WidgetPreRemove(pWidget);
  pWidget->AddInvalidateRect();
}
