// 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 "fpdfsdk/fpdfxfa/cpdfxfa_context.h"

#include <stdint.h>

#include <algorithm>
#include <utility>

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_seekablemultistream.h"
#include "core/fxcodec/jpeg/jpeg_progressive_decoder.h"
#include "core/fxcrt/autonuller.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/fixed_size_data_vector.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxcrt/xml/cfx_xmldocument.h"
#include "core/fxcrt/xml/cfx_xmlparser.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
#include "fxbarcode/BC_Library.h"
#include "fxjs/cjs_runtime.h"
#include "fxjs/ijs_runtime.h"
#include "public/fpdf_formfill.h"
#include "v8/include/cppgc/allocation.h"
#include "xfa/fgas/font/cfgas_gemodule.h"
#include "xfa/fxfa/cxfa_eventparam.h"
#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/cxfa_ffdocview.h"
#include "xfa/fxfa/cxfa_ffpageview.h"
#include "xfa/fxfa/cxfa_ffwidgethandler.h"
#include "xfa/fxfa/cxfa_fontmgr.h"
#include "xfa/fxfa/cxfa_readynodeiterator.h"

#ifdef PDF_ENABLE_XFA_BMP
#include "core/fxcodec/bmp/bmp_progressive_decoder.h"
#endif

#ifdef PDF_ENABLE_XFA_GIF
#include "core/fxcodec/gif/gif_progressive_decoder.h"
#endif

namespace {

bool IsValidAlertButton(int type) {
  return type == JSPLATFORM_ALERT_BUTTON_OK ||
         type == JSPLATFORM_ALERT_BUTTON_OKCANCEL ||
         type == JSPLATFORM_ALERT_BUTTON_YESNO ||
         type == JSPLATFORM_ALERT_BUTTON_YESNOCANCEL;
}

bool IsValidAlertIcon(int type) {
  return type == JSPLATFORM_ALERT_ICON_ERROR ||
         type == JSPLATFORM_ALERT_ICON_WARNING ||
         type == JSPLATFORM_ALERT_ICON_QUESTION ||
         type == JSPLATFORM_ALERT_ICON_STATUS ||
         type == JSPLATFORM_ALERT_ICON_ASTERISK;
}

RetainPtr<CPDF_SeekableMultiStream> CreateXFAMultiStream(
    const CPDF_Document* pPDFDoc) {
  const CPDF_Dictionary* pRoot = pPDFDoc->GetRoot();
  if (!pRoot)
    return nullptr;

  RetainPtr<const CPDF_Dictionary> pAcroForm = pRoot->GetDictFor("AcroForm");
  if (!pAcroForm)
    return nullptr;

  RetainPtr<const CPDF_Object> pElementXFA =
      pAcroForm->GetDirectObjectFor("XFA");
  if (!pElementXFA)
    return nullptr;

  std::vector<RetainPtr<const CPDF_Stream>> xfa_streams;
  if (pElementXFA->IsArray()) {
    const CPDF_Array* pXFAArray = pElementXFA->AsArray();
    for (size_t i = 0; i < pXFAArray->size() / 2; i++) {
      RetainPtr<const CPDF_Stream> pStream = pXFAArray->GetStreamAt(i * 2 + 1);
      if (pStream)
        xfa_streams.push_back(std::move(pStream));
    }
  } else if (pElementXFA->IsStream()) {
    xfa_streams.push_back(ToStream(pElementXFA));
  }
  if (xfa_streams.empty())
    return nullptr;

  return pdfium::MakeRetain<CPDF_SeekableMultiStream>(std::move(xfa_streams));
}

}  // namespace

void CPDFXFA_ModuleInit() {
  CFGAS_GEModule::Create();
  BC_Library_Init();
#ifdef PDF_ENABLE_XFA_BMP
  fxcodec::BmpProgressiveDecoder::InitializeGlobals();
#endif
#ifdef PDF_ENABLE_XFA_GIF
  fxcodec::GifProgressiveDecoder::InitializeGlobals();
#endif
  fxcodec::JpegProgressiveDecoder::InitializeGlobals();
}

void CPDFXFA_ModuleDestroy() {
  fxcodec::JpegProgressiveDecoder::DestroyGlobals();
#ifdef PDF_ENABLE_XFA_GIF
  fxcodec::GifProgressiveDecoder::DestroyGlobals();
#endif
#ifdef PDF_ENABLE_XFA_BMP
  fxcodec::BmpProgressiveDecoder::DestroyGlobals();
#endif
  BC_Library_Destroy();
  CFGAS_GEModule::Destroy();
}

CPDFXFA_Context::CPDFXFA_Context(CPDF_Document* pPDFDoc)
    : m_pPDFDoc(pPDFDoc),
      m_pDocEnv(std::make_unique<CPDFXFA_DocEnvironment>(this)),
      m_pGCHeap(FXGC_CreateHeap()) {
  DCHECK(m_pPDFDoc);

  // There might not be a heap when JS not initialized.
  if (m_pGCHeap) {
    m_pXFAApp = cppgc::MakeGarbageCollected<CXFA_FFApp>(
        m_pGCHeap->GetAllocationHandle(), this);
  }
}

CPDFXFA_Context::~CPDFXFA_Context() {
  m_nLoadStatus = LoadStatus::kClosing;
  if (m_pFormFillEnv)
    m_pFormFillEnv->ClearAllFocusedAnnots();
}

void CPDFXFA_Context::SetFormFillEnv(
    CPDFSDK_FormFillEnvironment* pFormFillEnv) {
  // The layout data can have pointers back into the script context. That
  // context will be different if the form fill environment closes, so, force
  // the layout data to clear.
  if (m_pXFADoc && m_pXFADoc->GetXFADoc()) {
    m_pXFADoc->GetXFADoc()->ClearLayoutData();
    m_pXFADocView.Clear();
    m_pXFADoc.Clear();
    m_pXFAApp.Clear();
    FXGC_ForceGarbageCollection(m_pGCHeap.get());
  }
  m_pFormFillEnv.Reset(pFormFillEnv);
}

bool CPDFXFA_Context::LoadXFADoc() {
  m_nLoadStatus = LoadStatus::kLoading;
  m_XFAPageList.clear();

  CJS_Runtime* actual_runtime = GetCJSRuntime();  // Null if a stub.
  if (!actual_runtime) {
    FXSYS_SetLastError(FPDF_ERR_XFALOAD);
    return false;
  }

  auto stream = CreateXFAMultiStream(m_pPDFDoc);
  if (!stream) {
    FXSYS_SetLastError(FPDF_ERR_XFALOAD);
    return false;
  }

  CFX_XMLParser parser(stream);
  m_pXML = parser.Parse();
  if (!m_pXML) {
    FXSYS_SetLastError(FPDF_ERR_XFALOAD);
    return false;
  }

  AutoNuller<cppgc::Persistent<CXFA_FFDoc>> doc_nuller(&m_pXFADoc);
  m_pXFADoc = cppgc::MakeGarbageCollected<CXFA_FFDoc>(
      m_pGCHeap->GetAllocationHandle(), m_pXFAApp, m_pDocEnv.get(), m_pPDFDoc,
      m_pGCHeap.get());

  if (!m_pXFADoc->OpenDoc(m_pXML.get())) {
    FXSYS_SetLastError(FPDF_ERR_XFALOAD);
    return false;
  }

  if (!m_pXFAApp->LoadFWLTheme(m_pXFADoc)) {
    FXSYS_SetLastError(FPDF_ERR_XFALAYOUT);
    return false;
  }

  m_pXFADoc->GetXFADoc()->InitScriptContext(actual_runtime);
  if (m_pXFADoc->GetFormType() == FormType::kXFAFull)
    m_FormType = FormType::kXFAFull;
  else
    m_FormType = FormType::kXFAForeground;

  AutoNuller<cppgc::Persistent<CXFA_FFDocView>> view_nuller(&m_pXFADocView);
  m_pXFADocView = m_pXFADoc->CreateDocView();

  if (m_pXFADocView->StartLayout() < 0) {
    m_pXFADoc->GetXFADoc()->ClearLayoutData();
    FXGC_ForceGarbageCollection(m_pGCHeap.get());
    FXSYS_SetLastError(FPDF_ERR_XFALAYOUT);
    return false;
  }

  m_pXFADocView->DoLayout();
  m_pXFADocView->StopLayout();

  view_nuller.AbandonNullification();
  doc_nuller.AbandonNullification();
  m_nLoadStatus = LoadStatus::kLoaded;
  return true;
}

int CPDFXFA_Context::GetPageCount() const {
  switch (m_FormType) {
    case FormType::kNone:
    case FormType::kAcroForm:
    case FormType::kXFAForeground:
      return m_pPDFDoc->GetPageCount();
    case FormType::kXFAFull:
      return m_pXFADoc ? m_pXFADocView->CountPageViews() : 0;
  }
}

RetainPtr<CPDFXFA_Page> CPDFXFA_Context::GetOrCreateXFAPage(int page_index) {
  if (page_index < 0)
    return nullptr;

  if (fxcrt::IndexInBounds(m_XFAPageList, page_index)) {
    if (m_XFAPageList[page_index])
      return m_XFAPageList[page_index];
  } else {
    m_nPageCount = GetPageCount();
    m_XFAPageList.resize(m_nPageCount);
  }

  auto pPage = pdfium::MakeRetain<CPDFXFA_Page>(GetPDFDoc(), page_index);
  if (!pPage->LoadPage())
    return nullptr;

  if (fxcrt::IndexInBounds(m_XFAPageList, page_index))
    m_XFAPageList[page_index] = pPage;

  return pPage;
}

RetainPtr<CPDFXFA_Page> CPDFXFA_Context::GetXFAPage(int page_index) {
  if (!fxcrt::IndexInBounds(m_XFAPageList, page_index))
    return nullptr;

  return m_XFAPageList[page_index];
}

RetainPtr<CPDFXFA_Page> CPDFXFA_Context::GetXFAPage(
    CXFA_FFPageView* pPage) const {
  if (!pPage)
    return nullptr;

  if (!m_pXFADoc)
    return nullptr;

  if (m_FormType != FormType::kXFAFull)
    return nullptr;

  for (auto& pTempPage : m_XFAPageList) {
    if (pTempPage && pTempPage->GetXFAPageView() == pPage)
      return pTempPage;
  }
  return nullptr;
}

uint32_t CPDFXFA_Context::DeletePage(int page_index) {
  // Delete from the document first because, if GetPage was never called for
  // this |page_index| then |m_XFAPageList| may have size < |page_index| even
  // if it's a valid page in the document.
  uint32_t page_obj_num = m_pPDFDoc->DeletePage(page_index);

  if (fxcrt::IndexInBounds(m_XFAPageList, page_index)) {
    m_XFAPageList.erase(m_XFAPageList.begin() + page_index);
    for (int i = page_index; i < fxcrt::CollectionSize<int>(m_XFAPageList); i++) {
      if (m_XFAPageList[i]) {
        m_XFAPageList[i]->SetXFAPageViewIndex(i);
      }
    }
  }

  return page_obj_num;
}

bool CPDFXFA_Context::ContainsExtensionForm() const {
  return m_FormType == FormType::kXFAFull ||
         m_FormType == FormType::kXFAForeground;
}

bool CPDFXFA_Context::ContainsExtensionFullForm() const {
  return m_FormType == FormType::kXFAFull;
}

bool CPDFXFA_Context::ContainsExtensionForegroundForm() const {
  return m_FormType == FormType::kXFAForeground;
}

void CPDFXFA_Context::ClearChangeMark() {
  if (m_pFormFillEnv)
    m_pFormFillEnv->ClearChangeMark();
}

CJS_Runtime* CPDFXFA_Context::GetCJSRuntime() const {
  if (!m_pFormFillEnv)
    return nullptr;

  return m_pFormFillEnv->GetIJSRuntime()->AsCJSRuntime();
}

WideString CPDFXFA_Context::GetAppTitle() const {
  return WideString::FromASCII("PDFium");
}

WideString CPDFXFA_Context::GetAppName() {
  return m_pFormFillEnv ? m_pFormFillEnv->FFI_GetAppName() : WideString();
}

WideString CPDFXFA_Context::GetLanguage() {
  return m_pFormFillEnv ? m_pFormFillEnv->GetLanguage() : WideString();
}

WideString CPDFXFA_Context::GetPlatform() {
  return m_pFormFillEnv ? m_pFormFillEnv->GetPlatform() : WideString();
}

void CPDFXFA_Context::Beep(uint32_t dwType) {
  if (m_pFormFillEnv)
    m_pFormFillEnv->JS_appBeep(dwType);
}

int32_t CPDFXFA_Context::MsgBox(const WideString& wsMessage,
                                const WideString& wsTitle,
                                uint32_t dwIconType,
                                uint32_t dwButtonType) {
  if (!m_pFormFillEnv || m_nLoadStatus != LoadStatus::kLoaded)
    return -1;

  int iconType =
      IsValidAlertIcon(dwIconType) ? dwIconType : JSPLATFORM_ALERT_ICON_DEFAULT;
  int iButtonType = IsValidAlertButton(dwButtonType)
                        ? dwButtonType
                        : JSPLATFORM_ALERT_BUTTON_DEFAULT;
  return m_pFormFillEnv->JS_appAlert(wsMessage, wsTitle, iButtonType, iconType);
}

WideString CPDFXFA_Context::Response(const WideString& wsQuestion,
                                     const WideString& wsTitle,
                                     const WideString& wsDefaultAnswer,
                                     bool bMark) {
  if (!m_pFormFillEnv)
    return WideString();

  constexpr int kMaxWideChars = 1024;
  constexpr int kMaxBytes = kMaxWideChars * sizeof(uint16_t);
  auto buffer = FixedSizeDataVector<uint8_t>::Zeroed(kMaxBytes);
  pdfium::span<uint8_t> buffer_span = buffer.span();
  int byte_length = m_pFormFillEnv->JS_appResponse(
      wsQuestion, wsTitle, wsDefaultAnswer, WideString(), bMark, buffer_span);
  if (byte_length <= 0)
    return WideString();

  buffer_span = buffer_span.first(std::min<size_t>(kMaxBytes, byte_length));
  return WideString::FromUTF16LE(buffer_span);
}

RetainPtr<IFX_SeekableReadStream> CPDFXFA_Context::DownloadURL(
    const WideString& wsURL) {
  return m_pFormFillEnv ? m_pFormFillEnv->DownloadFromURL(wsURL) : nullptr;
}

bool CPDFXFA_Context::PostRequestURL(const WideString& wsURL,
                                     const WideString& wsData,
                                     const WideString& wsContentType,
                                     const WideString& wsEncode,
                                     const WideString& wsHeader,
                                     WideString& wsResponse) {
  if (!m_pFormFillEnv)
    return false;

  wsResponse = m_pFormFillEnv->PostRequestURL(wsURL, wsData, wsContentType,
                                              wsEncode, wsHeader);
  return true;
}

bool CPDFXFA_Context::PutRequestURL(const WideString& wsURL,
                                    const WideString& wsData,
                                    const WideString& wsEncode) {
  return m_pFormFillEnv &&
         m_pFormFillEnv->PutRequestURL(wsURL, wsData, wsEncode);
}

CFX_Timer::HandlerIface* CPDFXFA_Context::GetTimerHandler() const {
  return m_pFormFillEnv ? m_pFormFillEnv->GetTimerHandler() : nullptr;
}

cppgc::Heap* CPDFXFA_Context::GetGCHeap() const {
  return m_pGCHeap.get();
}

bool CPDFXFA_Context::SaveDatasetsPackage(
    const RetainPtr<IFX_SeekableStream>& pStream) {
  return SavePackage(pStream, XFA_HASHCODE_Datasets);
}

bool CPDFXFA_Context::SaveFormPackage(
    const RetainPtr<IFX_SeekableStream>& pStream) {
  return SavePackage(pStream, XFA_HASHCODE_Form);
}

bool CPDFXFA_Context::SavePackage(const RetainPtr<IFX_SeekableStream>& pStream,
                                  XFA_HashCode code) {
  CXFA_FFDocView* pXFADocView = GetXFADocView();
  if (!pXFADocView)
    return false;

  CXFA_FFDoc* ffdoc = pXFADocView->GetDoc();
  return ffdoc->SavePackage(ToNode(ffdoc->GetXFADoc()->GetXFAObject(code)),
                            pStream);
}

void CPDFXFA_Context::SendPostSaveToXFADoc() {
  if (!ContainsExtensionForm())
    return;

  CXFA_FFDocView* pXFADocView = GetXFADocView();
  if (!pXFADocView)
    return;

  CXFA_FFWidgetHandler* pWidgetHandler = pXFADocView->GetWidgetHandler();
  CXFA_ReadyNodeIterator it(pXFADocView->GetRootSubform());
  while (CXFA_Node* pNode = it.MoveToNext()) {
    CXFA_EventParam preParam(XFA_EVENT_PostSave);
    preParam.m_bTargeted = false;
    pWidgetHandler->ProcessEvent(pNode, &preParam);
  }
  pXFADocView->UpdateDocView();
  ClearChangeMark();
}

void CPDFXFA_Context::SendPreSaveToXFADoc(
    std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
  if (!ContainsExtensionForm())
    return;

  CXFA_FFDocView* pXFADocView = GetXFADocView();
  if (!pXFADocView)
    return;

  CXFA_FFWidgetHandler* pWidgetHandler = pXFADocView->GetWidgetHandler();
  CXFA_ReadyNodeIterator it(pXFADocView->GetRootSubform());
  while (CXFA_Node* pNode = it.MoveToNext()) {
    CXFA_EventParam preParam(XFA_EVENT_PreSave);
    preParam.m_bTargeted = false;
    pWidgetHandler->ProcessEvent(pNode, &preParam);
  }
  pXFADocView->UpdateDocView();
  return;
}
