// Copyright 2016 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

#ifndef CORE_FPDFAPI_PARSER_CPDF_DOCUMENT_H_
#define CORE_FPDFAPI_PARSER_CPDF_DOCUMENT_H_

#include <functional>
#include <memory>
#include <set>
#include <utility>
#include <vector>

#include "core/fpdfapi/page/cpdf_image.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/parser/cpdf_object.h"
#include "core/fpdfapi/parser/cpdf_parser.h"
#include "core/fpdfdoc/cpdf_linklist.h"
#include "core/fxcrt/observable.h"
#include "core/fxcrt/retain_ptr.h"

class CFX_Font;
class CFX_Matrix;
class CPDF_ColorSpace;
class CPDF_DocPageData;
class CPDF_DocRenderData;
class CPDF_Font;
class CPDF_FontEncoding;
class CPDF_IccProfile;
class CPDF_LinearizedHeader;
class CPDF_Object;
class CPDF_Pattern;
class CPDF_ReadValidator;
class CPDF_StreamAcc;
class IFX_SeekableReadStream;
class JBig2_DocumentContext;

#define FPDFPERM_MODIFY 0x0008
#define FPDFPERM_ANNOT_FORM 0x0020
#define FPDFPERM_FILL_FORM 0x0100
#define FPDFPERM_EXTRACT_ACCESS 0x0200

class CPDF_Document : public Observable<CPDF_Document>,
                      public CPDF_Parser::ParsedObjectsHolder {
 public:
  // Type from which the XFA extension can subclass itself.
  class Extension {
   public:
    virtual ~Extension() = default;
    virtual CPDF_Document* GetPDFDoc() const = 0;
    virtual int GetPageCount() const = 0;
    virtual void DeletePage(int page_index) = 0;
    virtual uint32_t GetUserPermissions() const = 0;
  };

  static const int kPageMaxNum = 0xFFFFF;

  CPDF_Document();
  ~CPDF_Document() override;

  Extension* GetExtension() const { return m_pExtension.get(); }
  void SetExtension(std::unique_ptr<Extension> pExt) {
    m_pExtension = std::move(pExt);
  }

  CPDF_Parser* GetParser() const { return m_pParser.get(); }
  CPDF_Dictionary* GetRoot() const { return m_pRootDict.Get(); }
  CPDF_Dictionary* GetInfo();

  void DeletePage(int iPage);
  int GetPageCount() const;
  bool IsPageLoaded(int iPage) const;
  CPDF_Dictionary* GetPageDictionary(int iPage);
  int GetPageIndex(uint32_t objnum);
  uint32_t GetUserPermissions() const;

  // Returns a valid pointer, unless it is called during destruction.
  CPDF_DocPageData* GetPageData() const { return m_pDocPage.get(); }

  void SetPageObjNum(int iPage, uint32_t objNum);

  std::unique_ptr<JBig2_DocumentContext>* CodecContext() {
    return &m_pCodecContext;
  }
  std::unique_ptr<CPDF_LinkList>* LinksContext() { return &m_pLinksContext; }

  CPDF_DocRenderData* GetRenderData() const { return m_pDocRender.get(); }

  // |pFontDict| must not be null.
  CPDF_Font* LoadFont(CPDF_Dictionary* pFontDict);
  CPDF_ColorSpace* LoadColorSpace(const CPDF_Object* pCSObj,
                                  const CPDF_Dictionary* pResources);

  CPDF_Pattern* LoadPattern(CPDF_Object* pObj,
                            bool bShading,
                            const CFX_Matrix& matrix);

  RetainPtr<CPDF_Image> LoadImageFromPageData(uint32_t dwStreamObjNum);
  RetainPtr<CPDF_StreamAcc> LoadFontFile(const CPDF_Stream* pStream);
  RetainPtr<CPDF_IccProfile> LoadIccProfile(const CPDF_Stream* pStream);

  //  CPDF_Parser::ParsedObjectsHolder overrides:
  bool TryInit() override;

  CPDF_Parser::Error LoadDoc(
      const RetainPtr<IFX_SeekableReadStream>& pFileAccess,
      const char* password);
  CPDF_Parser::Error LoadLinearizedDoc(
      const RetainPtr<CPDF_ReadValidator>& validator,
      const char* password);
  bool has_valid_cross_reference_table() const {
    return m_bHasValidCrossReferenceTable;
  }

  void LoadPages();
  void CreateNewDoc();
  CPDF_Dictionary* CreateNewPage(int iPage);

  void IncrementParsedPageCount() { ++m_ParsedPageCount; }
  uint32_t GetParsedPageCountForTesting() { return m_ParsedPageCount; }

  CPDF_Font* AddStandardFont(const char* font,
                             const CPDF_FontEncoding* pEncoding);
  CPDF_Font* AddFont(CFX_Font* pFont, int charset);

#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
  CPDF_Font* AddWindowsFont(LOGFONTA* pLogFont);
#endif

 protected:
  class StockFontClearer {
   public:
    explicit StockFontClearer(CPDF_Document* pDoc);
    ~StockFontClearer();

   private:
    UnownedPtr<CPDF_Document> const m_pDoc;
  };

  // Retrieve page count information by getting count value from the tree nodes
  int RetrievePageCount();
  // When this method is called, m_pTreeTraversal[level] exists.
  CPDF_Dictionary* TraversePDFPages(int iPage, int* nPagesToGo, size_t level);
  int FindPageIndex(const CPDF_Dictionary* pNode,
                    uint32_t* skip_count,
                    uint32_t objnum,
                    int* index,
                    int level) const;
  std::unique_ptr<CPDF_Object> ParseIndirectObject(uint32_t objnum) override;
  size_t CalculateEncodingDict(int charset, CPDF_Dictionary* pBaseDict);
  const CPDF_Dictionary* GetPagesDict() const;
  CPDF_Dictionary* GetPagesDict();
  CPDF_Dictionary* ProcessbCJK(
      CPDF_Dictionary* pBaseDict,
      int charset,
      ByteString basefont,
      std::function<void(wchar_t, wchar_t, CPDF_Array*)> Insert);
  bool InsertDeletePDFPage(CPDF_Dictionary* pPages,
                           int nPagesToGo,
                           CPDF_Dictionary* pPageDict,
                           bool bInsert,
                           std::set<CPDF_Dictionary*>* pVisited);
  bool InsertNewPage(int iPage, CPDF_Dictionary* pPageDict);
  void ResetTraversal();
  void SetParser(std::unique_ptr<CPDF_Parser> pParser);
  CPDF_Parser::Error HandleLoadResult(CPDF_Parser::Error error);

  std::unique_ptr<CPDF_Parser> m_pParser;
  UnownedPtr<CPDF_Dictionary> m_pRootDict;
  UnownedPtr<CPDF_Dictionary> m_pInfoDict;

  // Vector of pairs to know current position in the page tree. The index in the
  // vector corresponds to the level being described. The pair contains a
  // pointer to the dictionary being processed at the level, and an index of the
  // of the child being processed within the dictionary's /Kids array.
  std::vector<std::pair<CPDF_Dictionary*, size_t>> m_pTreeTraversal;

  // True if the CPDF_Parser succeeded without having to rebuild the cross
  // reference table.
  bool m_bHasValidCrossReferenceTable = false;

  // Index of the next page that will be traversed from the page tree.
  bool m_bReachedMaxPageLevel = false;
  int m_iNextPageToTraverse = 0;
  uint32_t m_ParsedPageCount = 0;

  std::unique_ptr<CPDF_DocRenderData> m_pDocRender;
  // Must be after |m_pDocRender|.
  std::unique_ptr<CPDF_DocPageData> m_pDocPage;

  std::unique_ptr<JBig2_DocumentContext> m_pCodecContext;
  std::unique_ptr<CPDF_LinkList> m_pLinksContext;
  std::vector<uint32_t> m_PageList;  // Page number to page's dict objnum.

  // Must be second to last.
  StockFontClearer m_StockFontClearer;

  // Must be last. Destroy the extension before any non-extension teardown.
  std::unique_ptr<Extension> m_pExtension;
};

#endif  // CORE_FPDFAPI_PARSER_CPDF_DOCUMENT_H_
