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

#ifndef CORE_FPDFAPI_EDIT_CPDF_CREATOR_H_
#define CORE_FPDFAPI_EDIT_CPDF_CREATOR_H_

#include <map>
#include <memory>
#include <vector>

#include "core/fxcrt/cfx_retain_ptr.h"
#include "core/fxcrt/fx_basic.h"

class CPDF_Array;
class CPDF_CryptoHandler;
class CPDF_Dictionary;
class CPDF_Document;
class CPDF_Object;
class CPDF_Parser;
class CPDF_XRefStream;

#define FPDFCREATE_INCREMENTAL 1
#define FPDFCREATE_NO_ORIGINAL 2
#define FPDFCREATE_PROGRESSIVE 4
#define FPDFCREATE_OBJECTSTREAM 8

CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& buf, const CPDF_Object* pObj);

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

  void RemoveSecurity();
  bool Create(const CFX_RetainPtr<IFX_WriteStream>& pFile, uint32_t flags = 0);
  int32_t Continue(IFX_Pause* pPause = nullptr);
  bool SetFileVersion(int32_t fileVersion = 17);

 private:
  friend class CPDF_ObjectStream;
  friend class CPDF_XRefStream;

  bool Create(uint32_t flags);
  void Clear();

  void InitOldObjNumOffsets();
  void InitNewObjNumOffsets();
  void InitID(bool bDefault = true);

  int32_t AppendObjectNumberToXRef(uint32_t objnum);

  int32_t WriteDoc_Stage1(IFX_Pause* pPause);
  int32_t WriteDoc_Stage2(IFX_Pause* pPause);
  int32_t WriteDoc_Stage3(IFX_Pause* pPause);
  int32_t WriteDoc_Stage4(IFX_Pause* pPause);

  int32_t WriteOldIndirectObject(uint32_t objnum);
  int32_t WriteOldObjs(IFX_Pause* pPause);
  int32_t WriteNewObjs(bool bIncremental, IFX_Pause* pPause);
  int32_t WriteIndirectObj(const CPDF_Object* pObj);
  int32_t WriteDirectObj(uint32_t objnum,
                         const CPDF_Object* pObj,
                         bool bEncrypt = true);
  int32_t WriteIndirectObjectToStream(const CPDF_Object* pObj);
  int32_t WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj);
  int32_t WriteIndirectObjectToStream(uint32_t objnum,
                                      const uint8_t* pBuffer,
                                      uint32_t dwSize);

  int32_t WriteStream(const CPDF_Object* pStream,
                      uint32_t objnum,
                      CPDF_CryptoHandler* pCrypto);

  CPDF_Document* const m_pDocument;
  CPDF_Parser* const m_pParser;
  bool m_bSecurityChanged;
  CPDF_Dictionary* m_pEncryptDict;
  uint32_t m_dwEncryptObjNum;
  CFX_RetainPtr<CPDF_CryptoHandler> m_pCryptoHandler;
  CPDF_Object* m_pMetadata;
  std::unique_ptr<CPDF_XRefStream> m_pXRefStream;
  int32_t m_ObjectStreamSize;
  uint32_t m_dwLastObjNum;
  CFX_FileBufferArchive m_File;
  FX_FILESIZE m_Offset;
  FX_FILESIZE m_SavedOffset;
  int32_t m_iStage;
  uint32_t m_dwFlags;
  uint32_t m_CurObjNum;
  FX_FILESIZE m_XrefStart;
  std::map<uint32_t, FX_FILESIZE> m_ObjectOffsets;
  std::vector<uint32_t> m_NewObjNumArray;  // Sorted, ascending.
  std::unique_ptr<CPDF_Array> m_pIDArray;
  int32_t m_FileVersion;
};

#endif  // CORE_FPDFAPI_EDIT_CPDF_CREATOR_H_
