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

#include <algorithm>
#include <memory>
#include <vector>

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
#include "core/fpdfdoc/cpdf_nametree.h"
#include "core/fxcrt/cfx_memorystream.h"
#include "core/fxcrt/cfx_seekablemultistream.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/xml/cfx_xmlelement.h"
#include "core/fxcrt/xml/cfx_xmlnode.h"
#include "fxjs/xfa/cjx_object.h"
#include "third_party/base/ptr_util.h"
#include "xfa/fwl/cfwl_notedriver.h"
#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/cxfa_ffdocview.h"
#include "xfa/fxfa/cxfa_ffnotify.h"
#include "xfa/fxfa/cxfa_ffwidget.h"
#include "xfa/fxfa/cxfa_fontmgr.h"
#include "xfa/fxfa/parser/cxfa_acrobat.h"
#include "xfa/fxfa/parser/cxfa_acrobat7.h"
#include "xfa/fxfa/parser/cxfa_dataexporter.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_document_parser.h"
#include "xfa/fxfa/parser/cxfa_dynamicrender.h"
#include "xfa/fxfa/parser/cxfa_node.h"

CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment)
    : m_pDocEnvironment(pDocEnvironment), m_pApp(pApp) {}

CXFA_FFDoc::~CXFA_FFDoc() {
  CloseDoc();
}

bool CXFA_FFDoc::ParseDoc(CPDF_Object* pElementXFA) {
  std::vector<CPDF_Stream*> xfaStreams;
  if (pElementXFA->IsArray()) {
    CPDF_Array* pXFAArray = (CPDF_Array*)pElementXFA;
    for (size_t i = 0; i < pXFAArray->GetCount() / 2; i++) {
      if (CPDF_Stream* pStream = pXFAArray->GetStreamAt(i * 2 + 1))
        xfaStreams.push_back(pStream);
    }
  } else if (pElementXFA->IsStream()) {
    xfaStreams.push_back(pElementXFA->AsStream());
  }
  if (xfaStreams.empty())
    return false;

  auto stream = pdfium::MakeRetain<CFX_SeekableMultiStream>(xfaStreams);

  CXFA_DocumentParser parser(m_pDocument.get());
  if (!parser.Parse(stream, XFA_PacketType::Xdp))
    return false;

  m_pXMLRoot = parser.GetXMLRoot();
  m_pDocument->SetRoot(parser.GetRootNode());
  return true;
}

CXFA_FFDocView* CXFA_FFDoc::CreateDocView() {
  if (!m_DocView)
    m_DocView = pdfium::MakeUnique<CXFA_FFDocView>(this);

  return m_DocView.get();
}

CXFA_FFDocView* CXFA_FFDoc::GetDocView(CXFA_LayoutProcessor* pLayout) {
  return m_DocView && m_DocView->GetXFALayout() == pLayout ? m_DocView.get()
                                                           : nullptr;
}

CXFA_FFDocView* CXFA_FFDoc::GetDocView() {
  return m_DocView.get();
}

bool CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) {
  if (!pPDFDoc)
    return false;

  const CPDF_Dictionary* pRoot = pPDFDoc->GetRoot();
  if (!pRoot)
    return false;

  CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
  if (!pAcroForm)
    return false;

  CPDF_Object* pElementXFA = pAcroForm->GetDirectObjectFor("XFA");
  if (!pElementXFA)
    return false;

  m_pPDFDoc = pPDFDoc;

  m_pNotify = pdfium::MakeUnique<CXFA_FFNotify>(this);
  m_pDocument = pdfium::MakeUnique<CXFA_Document>(m_pNotify.get());
  if (!ParseDoc(pElementXFA))
    return false;

  // At this point we've got an XFA document and we want to always return
  // true to signify the load succeeded.

  m_pPDFFontMgr = pdfium::MakeUnique<CFGAS_PDFFontMgr>(
      GetPDFDoc(), GetApp()->GetFDEFontMgr());

  m_FormType = FormType::kXFAForeground;
  CXFA_Node* pConfig = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config));
  if (!pConfig)
    return true;

  CXFA_Acrobat* pAcrobat =
      pConfig->GetFirstChildByClass<CXFA_Acrobat>(XFA_Element::Acrobat);
  if (!pAcrobat)
    return true;

  CXFA_Acrobat7* pAcrobat7 =
      pAcrobat->GetFirstChildByClass<CXFA_Acrobat7>(XFA_Element::Acrobat7);
  if (!pAcrobat7)
    return true;

  CXFA_DynamicRender* pDynamicRender =
      pAcrobat7->GetFirstChildByClass<CXFA_DynamicRender>(
          XFA_Element::DynamicRender);
  if (!pDynamicRender)
    return true;

  WideString wsType = pDynamicRender->JSObject()->GetContent(false);
  if (wsType == L"required")
    m_FormType = FormType::kXFAFull;

  return true;
}

void CXFA_FFDoc::CloseDoc() {
  if (m_DocView) {
    m_DocView->RunDocClose();
    m_DocView.reset();
  }
  if (m_pDocument) {
    m_pDocument->ReleaseXMLNodesIfNeeded();
    m_pDocument->ClearLayoutData();
  }

  m_pDocument.reset();
  m_pXMLRoot.reset();
  m_pNotify.reset();
  m_pPDFFontMgr.reset();
  m_HashToDibDpiMap.clear();
  m_pApp->ClearEventTargets();
}

RetainPtr<CFX_DIBitmap> CXFA_FFDoc::GetPDFNamedImage(
    const WideStringView& wsName,
    int32_t& iImageXDpi,
    int32_t& iImageYDpi) {
  if (!m_pPDFDoc)
    return nullptr;

  uint32_t dwHash = FX_HashCode_GetW(wsName, false);
  auto it = m_HashToDibDpiMap.find(dwHash);
  if (it != m_HashToDibDpiMap.end()) {
    iImageXDpi = it->second.iImageXDpi;
    iImageYDpi = it->second.iImageYDpi;
    return it->second.pDibSource.As<CFX_DIBitmap>();
  }

  const CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot();
  if (!pRoot)
    return nullptr;

  CPDF_Dictionary* pNames = pRoot->GetDictFor("Names");
  if (!pNames)
    return nullptr;

  CPDF_Dictionary* pXFAImages = pNames->GetDictFor("XFAImages");
  if (!pXFAImages)
    return nullptr;

  CPDF_NameTree nametree(pXFAImages);
  CPDF_Object* pObject = nametree.LookupValue(WideString(wsName));
  if (!pObject) {
    for (size_t i = 0; i < nametree.GetCount(); i++) {
      WideString wsTemp;
      CPDF_Object* pTempObject = nametree.LookupValueAndName(i, &wsTemp);
      if (wsTemp == wsName) {
        pObject = pTempObject;
        break;
      }
    }
  }

  CPDF_Stream* pStream = ToStream(pObject);
  if (!pStream)
    return nullptr;

  auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
  pAcc->LoadAllDataFiltered();

  RetainPtr<IFX_SeekableStream> pImageFileRead =
      pdfium::MakeRetain<CFX_MemoryStream>(
          const_cast<uint8_t*>(pAcc->GetData()), pAcc->GetSize(), false);

  RetainPtr<CFX_DIBitmap> pDibSource = XFA_LoadImageFromBuffer(
      pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi);
  m_HashToDibDpiMap[dwHash] = {pDibSource, iImageXDpi, iImageYDpi};
  return pDibSource;
}

bool CXFA_FFDoc::SavePackage(CXFA_Node* pNode,
                             const RetainPtr<IFX_SeekableStream>& pFile) {
  ASSERT(pNode || GetXFADoc()->GetRoot());

  CXFA_DataExporter exporter;
  return exporter.Export(pFile, pNode ? pNode : GetXFADoc()->GetRoot());
}
