#ifndef FS_OFD_PACKAGE_H_
#define FS_OFD_PACKAGE_H_

#include "common/fs_common.h"
#include "ofd/fs_ofddoc.h"

/**
 * @brief Foxit 命名空间。
 *
 * @details Foxit PDF SDK 的所有定义和类都在此命名空间内定义。
 */
namespace foxit {
/**
 * @brief ofd 命名空间。
 */
namespace ofd {
class OFDDoc;

/**
* 此类表示和OFD包相关的方法。
* 在使用“OFD”模块之前，请确保已通过 @link common::Library::Initialize @endlink 函数成功初始化 Foxit PDF SDK，
* 且初始化时使用的密钥包含“OFD”模块。
*
* @详见 @link common::Library @endlink
*/
class OFDPackage FS_FINAL : public Base {
 public:
  /**
   * @brief 构造函数。
   *
   * @details 此构造函数用于构造新的OFD包（没有任何数据）。
   */
  OFDPackage();

  /**
   * @brief 构造函数，从现有OFD包文件路径。
   *
   * @param[in] path  现有OFD包文件的完整路径。它不应该是空字符串。
   */
  explicit OFDPackage(const char* path);

  /**
   * @brief 构造函数，从现有OFD包文件路径。
   *
   * @param[in] path  现有OFD包文件的完整路径。它不应该是空字符串。
   */
  explicit OFDPackage(const wchar_t* path);

  /**
   * @brief 构造函数，从内存缓冲区。
   *
   * @param[in] buffer    包含序列化文档的内存缓冲区。OFD文件包数据应完全加载在此内存缓冲区中。
   *                      它不应该是 <b>NULL</b>。
   * @param[in] size      内存缓冲区的大小。它应该大于0。
   */
  explicit OFDPackage(const void* buffer, size_t size);

  /**
   * @brief 构造函数，使用文件读取回调对象。
   *
   * @param[in] file_read  由用户实现的 @link common::file::ReaderCallback @endlink 对象，用于
   *                       加载OFD文件包。它不应该是 <b>NULL</b>。
   */
  explicit OFDPackage(common::file::ReaderCallback* file_reader);

  /** @brief 析构函数。 */
  ~OFDPackage();

  /**
   * @brief 构造函数，通过另一个OFD文件包对象。
   *
   * @param[in] other  另一个OFD文件包对象。
   */
  OFDPackage(const OFDPackage& other);

  /**
   * @brief 赋值操作符。
   *
   * @param[in] other  另一个OFD文件包对象，其值将被赋给当前对象。
   *
   * @return 当前对象自身的引用。
   */
  OFDPackage& operator = (const OFDPackage& other);

  /**
   * @brief 相等操作符。
   *
   * @param[in] other  另一个OFD文件包对象。此函数将检查当前对象是否等于这个对象。
   *
   * @return <b>true</b> 表示相等，<b>false</b> 表示不相等。
   */
  bool operator == (const OFDPackage& other) const;

  /**
   * @brief 不等操作符。
   *
   * @param[in] other  另一个OFD文件包对象。此函数将检查当前对象是否不等于这个对象。
   *
   * @return <b>true</b> 表示不相等，<b>false</b> 表示相等。
   */
  bool operator != (const OFDPackage& other) const;

  /**
   * @brief 检查当前对象是否为空。
   *
   * @details 当前对象为空时，表示当前对象是无用的。
   *
   * @return <b>true</b> 表示当前对象为空，<b>false</b> 表示不为空。
   */
  bool IsEmpty() const;

  /**
   * @brief 检查OFD文档是否被加密。
   *
   * @param[in] document_index  文档索引。有效范围：从0到(<i>count</i>-1)。
   *                            <i>count</i> 由函数 @link OFDPagckage::GetDocumentCount @endlink 返回。
   *
   * @return <b>true</b> 表示文档被加密，<b>false</b> 表示文档没有被加密。
   */
  bool IsEncrypted(int document_index);

  /**
   * @brief 获取OFD文档加密方法。
   *
   * @param[in] document_index  文档索引。有效范围：从0到(<i>count</i>-1)。
   *                            <i>count</i> 由函数 @link OFDPagckage::GetDocumentCount @endlink 返回。
   *
   * @return 文档加密方法。请参考从 @link OFDDoc::e_OFDEncryptMethodNone @endlink 开始的值，
   *         这将是这些值中的一个。
   */
  OFDDoc::EncryptMethod GetEncryptMethod(int document_index);

  /**
   * @brief 获取OFD文档加密类型。
   *
   * @param[in] document_index  文档索引。有效范围：从0到(<i>count</i>-1)。
   *                            <i>count</i> 由函数 @link OFDPagckage::GetDocumentCount @endlink 返回。
   *
   * @return 文档加密类型。请参考从 @link OFDDoc::e_OFDEncryptTypeNone @endlink 开始的值，
   *         这将是这些值中的一个。
   */
  OFDDoc::EncryptType GetEncryptType(int document_index);

  /**
   * @brief 检查OFD文件是否符合规范。
   *
   * @return <b>true</b> 表示文件符合规范，<b>false</b> 表示文件不符合规范。
   */
  bool Verify();

  /**
   * @brief 设置保存时文件中浮点类型数字的保留小数位数。
   *
   * @param[in] float_bit 保留小数位数，如果设置0，则默认按照源文档输出。如果小于0，则按照0处理。
   *
   * @return 无。
   */
  void SetFloatBit(int float_bit);

  /**
   * @brief 启用或禁用保存时字体内嵌。
   *
   * @param[in] embed_font <b>true</b> 表示启用字体内嵌，<b>false</b> 禁用字体内嵌。默认值：<b>false</b>。
   *
   * @return 无。
   */
  void EnableEmbedFont(bool embed_font);

  /**
   * @brief 启用或禁用保存时资源优化。
   *
   * @param[in] is_optimize_resource <b>true</b> 表示启用资源优化，<b>false</b> 禁用资源优化。默认值：<b>false</b>。
   *                                 此接口会将未使用的资源从文档中移除，不保证文件大小一定会减小。
   *
   * @return 无。
   */
  void EnableOptimizeResource(bool is_optimize_resource);

  /**
   * @brief 启用或禁用保存时文档灰度化。
   *
   * @param[in] gray_scale <b>true</b> 表示启用文档灰度化，<b>false</b> 禁用文档灰度化。默认值：<b>false</b>。
   *
   * @return 无。
   */
  void EnableDocumentGrayScale(bool gray_scale);

  /**
   * @brief 获取文件包中的OFD文档数量。
   *
   * @return OFD文档数量。
   */
  int GetDocumentCount();

  /**
   * @brief 加载OFD文档。
   *
   * @param[in] document_index  文档索引。有效范围：从0到(<i>count</i>-1)。
   *                            <i>count</i> 由函数 @link OFDPagckage::GetDocumentCount @endlink 返回。
   * @param[in] password       用于加载当前文档内容的密码字符串。密码可以是用户密码或所有者密码。
   *                           如果当前文档未使用密码加密，只需传递空字符串。默认值：空字符串。
   *
   * @return OFD文档对象。
   */
  OFDDoc LoadDocument(int document_index, const foxit::String& password);

 /**
  * @brief 添加空OFD文档。
  *
  * @return 新创建的OFD文档对象。
  */
  OFDDoc AddBlankDocument();

  /**
   * @brief 保存OFD文件包。
   *
   * @return <b>true</b> 表示文档保存成功，<b>false</b> 表示文档保存失败。
   */
  bool Save();

  /**
   * @brief 将当前OFD文件另存为另一个OFD文件。
   *
   * @param[in] file_path   新保存的OFD文件的完整路径。它不应该是空字符串。
   *
   * @return <b>true</b> 表示文档保存成功，<b>false</b> 表示文档保存失败。
   */
  bool SaveAs(const String& file_path);

  /**
   * @brief 将当前OFD文件另存为另一个OFD文件。
   *
   * @param[in] file_path   新保存的OFD文件的完整路径。它不应该是空字符串。
   *
   * @return <b>true</b> 表示文档保存成功，<b>false</b> 表示文档保存失败。
   */
  bool SaveAs(const WString& file_path);

  /**
   * @brief 将当前OFD文件另存为另一个OFD文件。
   *
   * @param[in] file_writer 用户实现的 @link common::file::WriterCallback @endlink 对象，用于保存OFD文档。
   *
   * @return <b>true</b> 表示文档保存成功，<b>false</b> 表示文档保存失败。
   */
  bool SaveAs(common::file::WriterCallback* file_writer);

  /**
   * @brief 设置被插入的文件是否可以拆分回源文档。
   *
   * @param[in] is_file_splittable  <b>true</b> 表示可以拆分回源文档，<b>false</b> 表示不能拆分回源文档。
   *
   * @return 无。
   */
  void SetSplittable(bool is_splittable);

  /**
   * @brief 将当前已合并的OFD文件拆分回原未拆分前的文档。
   *
   * @param[in] dest_folder 拆分后文档保存的目标文件夹路径。
   *
   * @return 拆分文件后的路径数组。
   */
  foxit::WStringArray SplitAsSourceFile(const String& dest_folder);

  /**
   * @brief 将当前已合并的OFD文件拆分回原未拆分前的文档。
   *
   * @param[in] dest_folder 拆分后文档保存的目标文件夹路径。
   *
   * @return 拆分文件后的路径数组。
   */
  foxit::WStringArray SplitAsSourceFile(const WString& dest_folder);

  explicit OFDPackage(FS_HANDLE handle);
};

}  // namespace ofd
}  // namespace foxit

#endif  // FS_OFD_PACKAGE_H_
