// Copyright 2017 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 "fxjs/cjx_hostpseudomodel.h"

#include <memory>

#include "fxjs/cfxjse_arguments.h"
#include "fxjs/cfxjse_engine.h"
#include "fxjs/cfxjse_value.h"
#include "xfa/fxfa/cxfa_ffnotify.h"
#include "xfa/fxfa/parser/cscript_hostpseudomodel.h"
#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_node.h"
#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"

namespace {

CXFA_Node* ToNode(CFXJSE_Value* pValue, CFXJSE_Class* pClass) {
  return static_cast<CXFA_Node*>(pValue->ToHostObject(pClass));
}

int32_t FilterName(const WideStringView& wsExpression,
                   int32_t nStart,
                   WideString& wsFilter) {
  ASSERT(nStart > -1);
  int32_t iLength = wsExpression.GetLength();
  if (nStart >= iLength)
    return iLength;

  wchar_t* pBuf = wsFilter.GetBuffer(iLength - nStart);
  int32_t nCount = 0;
  const wchar_t* pSrc = wsExpression.unterminated_c_str();
  wchar_t wCur;
  while (nStart < iLength) {
    wCur = pSrc[nStart++];
    if (wCur == ',')
      break;

    pBuf[nCount++] = wCur;
  }
  wsFilter.ReleaseBuffer(nCount);
  wsFilter.TrimLeft();
  wsFilter.TrimRight();
  return nStart;
}

}  // namespace

CJX_HostPseudoModel::CJX_HostPseudoModel(CScript_HostPseudoModel* model)
    : CJX_Object(model) {}

CJX_HostPseudoModel::~CJX_HostPseudoModel() {}

CScript_HostPseudoModel* CJX_HostPseudoModel::GetXFAHostPseudoModel() {
  return static_cast<CScript_HostPseudoModel*>(GetXFAObject());
}

void CJX_HostPseudoModel::AppType(CFXJSE_Value* pValue,
                                  bool bSetting,
                                  XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  if (bSetting) {
    ThrowInvalidPropertyException();
    return;
  }
  pValue->SetString("Exchange");
}

void CJX_HostPseudoModel::CalculationsEnabled(CFXJSE_Value* pValue,
                                              bool bSetting,
                                              XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  if (bSetting) {
    pNotify->GetDocEnvironment()->SetCalculationsEnabled(hDoc,
                                                         pValue->ToBoolean());
    return;
  }
  pValue->SetBoolean(pNotify->GetDocEnvironment()->IsCalculationsEnabled(hDoc));
}

void CJX_HostPseudoModel::CurrentPage(CFXJSE_Value* pValue,
                                      bool bSetting,
                                      XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  if (bSetting) {
    pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, pValue->ToInteger());
    return;
  }
  pValue->SetInteger(pNotify->GetDocEnvironment()->GetCurrentPage(hDoc));
}

void CJX_HostPseudoModel::Language(CFXJSE_Value* pValue,
                                   bool bSetting,
                                   XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  if (bSetting) {
    ThrowException(L"Unable to set language value.");
    return;
  }
  pValue->SetString(
      pNotify->GetAppProvider()->GetLanguage().UTF8Encode().AsStringView());
}

void CJX_HostPseudoModel::NumPages(CFXJSE_Value* pValue,
                                   bool bSetting,
                                   XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  if (bSetting) {
    ThrowException(L"Unable to set numPages value.");
    return;
  }
  pValue->SetInteger(pNotify->GetDocEnvironment()->CountPages(hDoc));
}

void CJX_HostPseudoModel::Platform(CFXJSE_Value* pValue,
                                   bool bSetting,
                                   XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  if (bSetting) {
    ThrowException(L"Unable to set platform value.");
    return;
  }
  pValue->SetString(
      pNotify->GetAppProvider()->GetPlatform().UTF8Encode().AsStringView());
}

void CJX_HostPseudoModel::Title(CFXJSE_Value* pValue,
                                bool bSetting,
                                XFA_ATTRIBUTE eAttribute) {
  if (!GetXFAHostPseudoModel()
           ->GetDocument()
           ->GetScriptContext()
           ->IsRunAtClient())
    return;

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  if (bSetting) {
    pNotify->GetDocEnvironment()->SetTitle(hDoc, pValue->ToWideString());
    return;
  }

  WideString wsTitle;
  pNotify->GetDocEnvironment()->GetTitle(hDoc, wsTitle);
  pValue->SetString(wsTitle.UTF8Encode().AsStringView());
}

void CJX_HostPseudoModel::ValidationsEnabled(CFXJSE_Value* pValue,
                                             bool bSetting,
                                             XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  if (bSetting) {
    pNotify->GetDocEnvironment()->SetValidationsEnabled(hDoc,
                                                        pValue->ToBoolean());
    return;
  }

  bool bEnabled = pNotify->GetDocEnvironment()->IsValidationsEnabled(hDoc);
  pValue->SetBoolean(bEnabled);
}

void CJX_HostPseudoModel::Variation(CFXJSE_Value* pValue,
                                    bool bSetting,
                                    XFA_ATTRIBUTE eAttribute) {
  if (!GetXFAHostPseudoModel()
           ->GetDocument()
           ->GetScriptContext()
           ->IsRunAtClient())
    return;

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  if (bSetting) {
    ThrowException(L"Unable to set variation value.");
    return;
  }
  pValue->SetString("Full");
}

void CJX_HostPseudoModel::Version(CFXJSE_Value* pValue,
                                  bool bSetting,
                                  XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  if (bSetting) {
    ThrowException(L"Unable to set version value.");
    return;
  }
  pValue->SetString("11");
}

void CJX_HostPseudoModel::Name(CFXJSE_Value* pValue,
                               bool bSetting,
                               XFA_ATTRIBUTE eAttribute) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  if (bSetting) {
    ThrowInvalidPropertyException();
    return;
  }
  pValue->SetString(
      pNotify->GetAppProvider()->GetAppName().UTF8Encode().AsStringView());
}

void CJX_HostPseudoModel::GotoURL(CFXJSE_Arguments* pArguments) {
  if (!GetXFAHostPseudoModel()
           ->GetDocument()
           ->GetScriptContext()
           ->IsRunAtClient())
    return;

  int32_t iLength = pArguments->GetLength();
  if (iLength != 1) {
    ThrowParamCountMismatchException(L"gotoURL");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  WideString wsURL;
  if (iLength >= 1) {
    ByteString bsURL = pArguments->GetUTF8String(0);
    wsURL = WideString::FromUTF8(bsURL.AsStringView());
  }
  pNotify->GetDocEnvironment()->GotoURL(hDoc, wsURL);
}

void CJX_HostPseudoModel::OpenList(CFXJSE_Arguments* pArguments) {
  if (!GetXFAHostPseudoModel()
           ->GetDocument()
           ->GetScriptContext()
           ->IsRunAtClient())
    return;

  int32_t iLength = pArguments->GetLength();
  if (iLength != 1) {
    ThrowParamCountMismatchException(L"openList");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_Node* pNode = nullptr;
  if (iLength >= 1) {
    std::unique_ptr<CFXJSE_Value> pValue(pArguments->GetValue(0));
    if (pValue->IsObject()) {
      pNode = ToNode(pValue.get(), nullptr);
    } else if (pValue->IsString()) {
      CFXJSE_Engine* pScriptContext =
          GetXFAHostPseudoModel()->GetDocument()->GetScriptContext();
      if (!pScriptContext)
        return;

      CXFA_Object* pObject = pScriptContext->GetThisObject();
      if (!pObject)
        return;

      uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent |
                        XFA_RESOLVENODE_Siblings;
      XFA_RESOLVENODE_RS resoveNodeRS;
      int32_t iRet = pScriptContext->ResolveObjects(
          pObject, pValue->ToWideString().AsStringView(), resoveNodeRS, dwFlag);
      if (iRet < 1 || !resoveNodeRS.objects.front()->IsNode())
        return;

      pNode = resoveNodeRS.objects.front()->AsNode();
    }
  }

  CXFA_LayoutProcessor* pDocLayout =
      GetXFAHostPseudoModel()->GetDocument()->GetDocLayout();
  if (!pDocLayout)
    return;

  CXFA_FFWidget* hWidget =
      pNotify->GetHWidget(pDocLayout->GetLayoutItem(pNode));
  if (!hWidget)
    return;

  pNotify->GetDocEnvironment()->SetFocusWidget(pNotify->GetHDOC(), hWidget);
  pNotify->OpenDropDownList(hWidget);
}

void CJX_HostPseudoModel::Response(CFXJSE_Arguments* pArguments) {
  int32_t iLength = pArguments->GetLength();
  if (iLength < 1 || iLength > 4) {
    ThrowParamCountMismatchException(L"response");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  WideString wsQuestion;
  WideString wsTitle;
  WideString wsDefaultAnswer;
  bool bMark = false;
  if (iLength >= 1) {
    ByteString bsQuestion = pArguments->GetUTF8String(0);
    wsQuestion = WideString::FromUTF8(bsQuestion.AsStringView());
  }
  if (iLength >= 2) {
    ByteString bsTitle = pArguments->GetUTF8String(1);
    wsTitle = WideString::FromUTF8(bsTitle.AsStringView());
  }
  if (iLength >= 3) {
    ByteString bsDefaultAnswer = pArguments->GetUTF8String(2);
    wsDefaultAnswer = WideString::FromUTF8(bsDefaultAnswer.AsStringView());
  }
  if (iLength >= 4) {
    bMark = pArguments->GetInt32(3) == 0 ? false : true;
  }

  WideString wsAnswer = pNotify->GetAppProvider()->Response(
      wsQuestion, wsTitle, wsDefaultAnswer, bMark);
  CFXJSE_Value* pValue = pArguments->GetReturnValue();
  if (pValue)
    pValue->SetString(wsAnswer.UTF8Encode().AsStringView());
}

void CJX_HostPseudoModel::DocumentInBatch(CFXJSE_Arguments* pArguments) {
  if (CFXJSE_Value* pValue = pArguments->GetReturnValue())
    pValue->SetInteger(0);
}

void CJX_HostPseudoModel::ResetData(CFXJSE_Arguments* pArguments) {
  int32_t iLength = pArguments->GetLength();
  if (iLength < 0 || iLength > 1) {
    ThrowParamCountMismatchException(L"resetData");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  WideString wsExpression;
  if (iLength >= 1) {
    ByteString bsExpression = pArguments->GetUTF8String(0);
    wsExpression = WideString::FromUTF8(bsExpression.AsStringView());
  }
  if (wsExpression.IsEmpty()) {
    pNotify->ResetData();
    return;
  }

  int32_t iStart = 0;
  WideString wsName;
  CXFA_Node* pNode = nullptr;
  int32_t iExpLength = wsExpression.GetLength();
  while (iStart < iExpLength) {
    iStart = FilterName(wsExpression.AsStringView(), iStart, wsName);
    CFXJSE_Engine* pScriptContext =
        GetXFAHostPseudoModel()->GetDocument()->GetScriptContext();
    if (!pScriptContext)
      return;

    CXFA_Object* pObject = pScriptContext->GetThisObject();
    if (!pObject)
      return;

    uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent |
                      XFA_RESOLVENODE_Siblings;
    XFA_RESOLVENODE_RS resoveNodeRS;
    int32_t iRet = pScriptContext->ResolveObjects(
        pObject, wsName.AsStringView(), resoveNodeRS, dwFlag);
    if (iRet < 1 || !resoveNodeRS.objects.front()->IsNode())
      continue;

    pNode = resoveNodeRS.objects.front()->AsNode();
    pNotify->ResetData(pNode->GetWidgetData());
  }
  if (!pNode)
    pNotify->ResetData();
}

void CJX_HostPseudoModel::Beep(CFXJSE_Arguments* pArguments) {
  if (!GetXFAHostPseudoModel()
           ->GetDocument()
           ->GetScriptContext()
           ->IsRunAtClient())
    return;

  int32_t iLength = pArguments->GetLength();
  if (iLength < 0 || iLength > 1) {
    ThrowParamCountMismatchException(L"beep");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  uint32_t dwType = 4;
  if (iLength >= 1)
    dwType = pArguments->GetInt32(0);

  pNotify->GetAppProvider()->Beep(dwType);
}

void CJX_HostPseudoModel::SetFocus(CFXJSE_Arguments* pArguments) {
  if (!GetXFAHostPseudoModel()
           ->GetDocument()
           ->GetScriptContext()
           ->IsRunAtClient())
    return;

  int32_t iLength = pArguments->GetLength();
  if (iLength != 1) {
    ThrowParamCountMismatchException(L"setFocus");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_Node* pNode = nullptr;
  if (iLength >= 1) {
    std::unique_ptr<CFXJSE_Value> pValue(pArguments->GetValue(0));
    if (pValue->IsObject()) {
      pNode = ToNode(pValue.get(), nullptr);
    } else if (pValue->IsString()) {
      CFXJSE_Engine* pScriptContext =
          GetXFAHostPseudoModel()->GetDocument()->GetScriptContext();
      if (!pScriptContext)
        return;

      CXFA_Object* pObject = pScriptContext->GetThisObject();
      if (!pObject)
        return;

      uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent |
                        XFA_RESOLVENODE_Siblings;
      XFA_RESOLVENODE_RS resoveNodeRS;
      int32_t iRet = pScriptContext->ResolveObjects(
          pObject, pValue->ToWideString().AsStringView(), resoveNodeRS, dwFlag);
      if (iRet < 1 || !resoveNodeRS.objects.front()->IsNode())
        return;

      pNode = resoveNodeRS.objects.front()->AsNode();
    }
  }
  pNotify->SetFocusWidgetNode(pNode);
}

void CJX_HostPseudoModel::GetFocus(CFXJSE_Arguments* pArguments) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_Node* pNode = pNotify->GetFocusWidgetNode();
  if (!pNode)
    return;

  pArguments->GetReturnValue()->Assign(GetXFAHostPseudoModel()
                                           ->GetDocument()
                                           ->GetScriptContext()
                                           ->GetJSValueFromMap(pNode));
}

void CJX_HostPseudoModel::MessageBox(CFXJSE_Arguments* pArguments) {
  if (!GetXFAHostPseudoModel()
           ->GetDocument()
           ->GetScriptContext()
           ->IsRunAtClient())
    return;

  int32_t iLength = pArguments->GetLength();
  if (iLength < 1 || iLength > 4) {
    ThrowParamCountMismatchException(L"messageBox");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  WideString wsMessage;
  WideString bsTitle;
  uint32_t dwMessageType = XFA_MBICON_Error;
  uint32_t dwButtonType = XFA_MB_OK;
  if (iLength >= 1) {
    if (!ValidateArgsForMsg(pArguments, 0, wsMessage))
      return;
  }
  if (iLength >= 2) {
    if (!ValidateArgsForMsg(pArguments, 1, bsTitle))
      return;
  }
  if (iLength >= 3) {
    dwMessageType = pArguments->GetInt32(2);
    if (dwMessageType > XFA_MBICON_Status)
      dwMessageType = XFA_MBICON_Error;
  }
  if (iLength >= 4) {
    dwButtonType = pArguments->GetInt32(3);
    if (dwButtonType > XFA_MB_YesNoCancel)
      dwButtonType = XFA_MB_OK;
  }

  int32_t iValue = pNotify->GetAppProvider()->MsgBox(
      wsMessage, bsTitle, dwMessageType, dwButtonType);
  CFXJSE_Value* pValue = pArguments->GetReturnValue();
  if (pValue)
    pValue->SetInteger(iValue);
}

bool CJX_HostPseudoModel::ValidateArgsForMsg(CFXJSE_Arguments* pArguments,
                                             int32_t iArgIndex,
                                             WideString& wsValue) {
  if (!pArguments || iArgIndex < 0)
    return false;

  bool bIsJsType = false;
  if (GetXFAHostPseudoModel()->GetDocument()->GetScriptContext()->GetType() ==
      XFA_SCRIPTLANGTYPE_Javascript) {
    bIsJsType = true;
  }

  std::unique_ptr<CFXJSE_Value> pValueArg(pArguments->GetValue(iArgIndex));
  if (!pValueArg->IsString() && bIsJsType) {
    ThrowArgumentMismatchException();
    return false;
  }
  wsValue = pValueArg->IsNull() ? L"" : pValueArg->ToWideString();
  return true;
}

void CJX_HostPseudoModel::DocumentCountInBatch(CFXJSE_Arguments* pArguments) {
  if (CFXJSE_Value* pValue = pArguments->GetReturnValue())
    pValue->SetInteger(0);
}

void CJX_HostPseudoModel::Print(CFXJSE_Arguments* pArguments) {
  if (!GetXFAHostPseudoModel()
           ->GetDocument()
           ->GetScriptContext()
           ->IsRunAtClient())
    return;

  int32_t iLength = pArguments->GetLength();
  if (iLength != 8) {
    ThrowParamCountMismatchException(L"print");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  uint32_t dwOptions = 0;
  bool bShowDialog = true;
  if (iLength >= 1)
    bShowDialog = pArguments->GetInt32(0) == 0 ? false : true;
  if (bShowDialog)
    dwOptions |= XFA_PRINTOPT_ShowDialog;

  int32_t nStartPage = 0;
  if (iLength >= 2)
    nStartPage = pArguments->GetInt32(1);

  int32_t nEndPage = 0;
  if (iLength >= 3)
    nEndPage = pArguments->GetInt32(2);

  bool bCanCancel = true;
  if (iLength >= 4)
    bCanCancel = pArguments->GetInt32(3) == 0 ? false : true;
  if (bCanCancel)
    dwOptions |= XFA_PRINTOPT_CanCancel;

  bool bShrinkPage = true;
  if (iLength >= 5)
    bShrinkPage = pArguments->GetInt32(4) == 0 ? false : true;
  if (bShrinkPage)
    dwOptions |= XFA_PRINTOPT_ShrinkPage;

  bool bAsImage = true;
  if (iLength >= 6)
    bAsImage = pArguments->GetInt32(5) == 0 ? false : true;
  if (bAsImage)
    dwOptions |= XFA_PRINTOPT_AsImage;

  bool bReverseOrder = true;
  if (iLength >= 7)
    bAsImage = pArguments->GetInt32(5) == 0 ? false : true;

  bReverseOrder = pArguments->GetInt32(6) == 0 ? false : true;
  if (bReverseOrder)
    dwOptions |= XFA_PRINTOPT_ReverseOrder;

  bool bPrintAnnot = true;
  if (iLength >= 8)
    bPrintAnnot = pArguments->GetInt32(7) == 0 ? false : true;
  if (bPrintAnnot)
    dwOptions |= XFA_PRINTOPT_PrintAnnot;

  pNotify->GetDocEnvironment()->Print(hDoc, nStartPage, nEndPage, dwOptions);
}

void CJX_HostPseudoModel::ImportData(CFXJSE_Arguments* pArguments) {
  int32_t iLength = pArguments->GetLength();
  if (iLength < 0 || iLength > 1) {
    ThrowParamCountMismatchException(L"importData");
    return;
  }
  // Not implemented.
}

void CJX_HostPseudoModel::ExportData(CFXJSE_Arguments* pArguments) {
  int32_t iLength = pArguments->GetLength();
  if (iLength < 0 || iLength > 2) {
    ThrowParamCountMismatchException(L"exportData");
    return;
  }

  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  WideString wsFilePath;
  bool bXDP = true;
  if (iLength >= 1) {
    ByteString bsFilePath = pArguments->GetUTF8String(0);
    wsFilePath = WideString::FromUTF8(bsFilePath.AsStringView());
  }
  if (iLength >= 2)
    bXDP = pArguments->GetInt32(1) == 0 ? false : true;

  pNotify->GetDocEnvironment()->ExportData(hDoc, wsFilePath, bXDP);
}

void CJX_HostPseudoModel::PageUp(CFXJSE_Arguments* pArguments) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  int32_t nCurPage = pNotify->GetDocEnvironment()->GetCurrentPage(hDoc);
  int32_t nNewPage = 0;
  if (nCurPage <= 1)
    return;

  nNewPage = nCurPage - 1;
  pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, nNewPage);
}

void CJX_HostPseudoModel::PageDown(CFXJSE_Arguments* pArguments) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
  int32_t nCurPage = pNotify->GetDocEnvironment()->GetCurrentPage(hDoc);
  int32_t nPageCount = pNotify->GetDocEnvironment()->CountPages(hDoc);
  if (!nPageCount || nCurPage == nPageCount)
    return;

  int32_t nNewPage = 0;
  if (nCurPage >= nPageCount)
    nNewPage = nPageCount - 1;
  else
    nNewPage = nCurPage + 1;

  pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, nNewPage);
}

void CJX_HostPseudoModel::CurrentDateTime(CFXJSE_Arguments* pArguments) {
  CXFA_FFNotify* pNotify = GetXFAHostPseudoModel()->GetDocument()->GetNotify();
  if (!pNotify)
    return;

  WideString wsDataTime = pNotify->GetCurrentDateTime();
  CFXJSE_Value* pValue = pArguments->GetReturnValue();
  if (pValue)
    pValue->SetString(wsDataTime.UTF8Encode().AsStringView());
}
