#ifndef FS_OFD_ATTACHMENT_H_
#define FS_OFD_ATTACHMENT_H_

#include "common/fs_common.h"

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

/** 此类代表了附件信息。 */
class AttachmentInfo FS_FINAL : public Object {
 public:
  /**
   * @brief 构造函数。
   */
  AttachmentInfo() {}

  /**
   * @brief 带参数的构造函数。
   *
   * @param[in] name               附件名称。
   * @param[in] format             附件格式。
   * @param[in] usage              附件用途。
   * @param[in] creation_date      附件创建日期。
   * @param[in] modification_date  附件修改日期。
   */
  explicit AttachmentInfo(const String& name, const String& format, const String& usage, const foxit::DateTime& creation_date, const foxit::DateTime& modification_date) :
    name(name),
    format(format),
    usage(usage),
    creation_date(creation_date),
    modification_date(modification_date) {}

  /**
   * @brief 构造函数，通过另一个附件信息对象。
   *
   * @param[in] other 另一个附件信息对象。
   */
  AttachmentInfo(const AttachmentInfo& other) {
    this->name = other.name;
    this->format = other.format;
    this->usage = other.usage;
    this->creation_date = other.creation_date;
    this->modification_date = other.modification_date;
  }

  /**
   * @brief 赋值操作符。
   *
   * @param[in] other 另一个附件信息对象，其值将被赋给当前对象。
   *
   * @return 当前对象自身的引用。
   */
  AttachmentInfo& operator = (const AttachmentInfo& other) {
    this->name = other.name;
    this->format = other.format;
    this->usage = other.usage;
    this->creation_date = other.creation_date;
    this->modification_date = other.modification_date;
    return *this;
  }

  /**
   * @brief 设置值。
   *
   * @param[in] name               附件名称。
   * @param[in] format             附件格式。
   * @param[in] usage              附件用途。
   * @param[in] creation_date      附件创建日期。
   * @param[in] modification_date  附件修改日期。
   *
   * @return 无。
   */
  void Set(const String& name, const String& format, const String& usage, const foxit::DateTime& creation_date, const foxit::DateTime& modification_date) {
    this->name = name;
    this->format = format;
    this->usage = usage;
    this->creation_date = creation_date;
    this->modification_date = modification_date;
  }

  /**
   * @brief 附件名称。
   *
   */
  String name;

  /**
   * @brief 附件格式。
   *
   */
  String format;

  /**
   * @brief 附件用途。
   *
   */
  String usage;

  /**
   * @brief 附件创建日期。
   *
   */
  foxit::DateTime creation_date;

  /**
   * @brief 附件修改日期。
   *
   */
  foxit::DateTime modification_date;
};

/** 此类表示和OFD附件相关的操作。 */
class Attachment FS_FINAL : public Base {
 public:
  /** @brief 析构函数。 */
  ~Attachment();

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

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

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

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

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

  /**
   * @brief 导出文件到指定路径。
   *
   * @param[in] file_path  指定的文件路径。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool GetFile(const String& file_path);

  /**
   * @brief 导出文件到指定路径。
   *
   * @param[in] file_path  指定的文件路径。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool GetFile(const WString& file_path);

  /**
   * @brief 通过文件写入回调导出文件。
   *
   * @param[in] file_writer 用户实现的 @link foxit::common::file::WriterCallback @endlink 对象，用于保存文件。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool GetFile(foxit::common::file::WriterCallback* file_writer);

  /**
   * @brief 获取ID。
   *
   * @return ID。
   */
  foxit::uint32 GetID();

  /**
   * @brief 获取修改者名称。
   *
   * @return 修改者名称。
   */
  String GetModifier();

  /**
   * @brief 获取描述。
   *
   * @return 描述。
   */
  String GetDescription();

  /**
   * @brief 获取附件信息。
   *
   * @return 附件信息。请参考 @link foxit::ofd::AttachmentInfo @endlink 。
   */
  AttachmentInfo GetAttachmentInfo();

  /**
   * @brief 检查附件是否可见。
   *
   * @return <b>true</b>表示可见，<b>false</b>表示不可见。
   */
  bool IsVisible();

  /**
   * @brief 检查附件是否可删除。
   *
   * @return <b>true</b>表示可删除，<b>false</b>表示不可删除。
   */
  bool IsDeletable();

  /**
   * @brief 检查附件是否可编辑。
   *
   * @return <b>true</b>表示可编辑，<b>false</b>表示不可编辑。
   */
  bool IsEditable();

  /**
   * @brief 检查附件是否可导出。
   *
   * @return <b>true</b>表示可导出，<b>false</b>表示不可导出。
   */
  bool IsExportable();

  /**
   * @brief 通过文件设置附件内容。
   *
   * @param[in] file_path  指定的文件路径。
   * @param[in] name       指定的附件名称。它可以是空字符串。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool SetFile(const String& file_path, const String& name = String());

  /**
   * @brief 通过文件设置附件内容。
   *
   * @param[in] file_path  指定的文件路径。
   * @param[in] name       指定的附件名称。它可以是空字符串。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool SetFile(const WString& file_path, const String& name = String());

  /**
   * @brief 通过文件读取回调设置附件内容。
   *
   * @param[in] file_reader 用户实现的 @link foxit::common::file::ReaderCallback @endlink 对象，用于读取文件内容。
   * @param[in] name        指定的附件名称。它可以是空字符串。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool SetFile(foxit::common::file::ReaderCallback* file_reader, const String& name = String());

  /**
   * @brief 设置名称。
   *
   * @param[in] name  名称。
   *
   * @return 无。
   */
  void SetName(const String& name);

  /**
   * @brief 设置格式。
   *
   * @param[in] format  格式。
   *
   * @return 无。
   */
  void SetFormat(const String& format);

  /**
   * @brief 设置用途。
   *
   * @param[in] usage  用途。
   *
   * @return 无。
   */
  void SetUsage(const String& usage);

  /**
   * @brief 设置创建日期。
   *
   * @param[in] creation_date  创建日期。请参考 @link foxit::DateTime @endlink 。
   *
   * @return 无。
   */
  void SetCreationDate(const foxit::DateTime& creation_date);

  /**
   * @brief 设置修改者名称。
   *
   * @param[in] modifier  修改者名称。
   *
   * @return 无。
   */
  void SetModifier(const String& modifier);

  /**
   * @brief 设置修改日期。
   *
   * @param[in] modification_date  修改日期。请参考 @link foxit::DateTime @endlink 。
   *
   * @return 无。
   */
  void SetModDate(const foxit::DateTime& modification_date);

  /**
   * @brief 设置描述。
   *
   * @param[in] description  描述。
   *
   * @return 无。
   */
  void SetDescription(const String& description);

  /**
   * @brief 设置附件信息。
   *
   * @param[in] info  附件信息。请参考 @link foxit::ofd::AttachmentInfo @endlink 。
   *
   * @return 无。
   */
  void SetAttachmentInfo(const AttachmentInfo& info);

  /**
   * @brief 设置附件可见性。
   *
   * @param[in] visible  是否可见。<b>true</b>表示可见，<b>false</b>表示不可见。
   *
   * @return 无。
   */
  void EnableVisible(bool visible);

  /**
   * @brief 设置附件可删除性。
   *
   * @param[in] deletable  是否可删除。<b>true</b>表示可删除，<b>false</b>表示不可删除。
   *
   * @return 无。
   */
  void EnableDeletable(bool deletable);

  /**
   * @brief 设置附件可编辑性。
   *
   * @param[in] editable  是否可编辑。<b>true</b>表示可编辑，<b>false</b>表示不可编辑。
   *
   * @return 无。
   */
  void EnableEditable(bool editable);

  /**
   * @brief 设置附件可导出性。
   *
   * @param[in] exportable  是否可导出。<b>true</b>表示可导出，<b>false</b>表示不可导出。
   *
   * @return 无。
   */
  void EnableExportable(bool exportable);

  explicit Attachment(FS_HANDLE handle);
};

/** 此类表示和OFD附件集合相关的操作。 */
class Attachments FS_FINAL : public Base{
 public:
  /**
    * @brief OFD电子凭证定义枚举类型。
    *
    * @details 该枚举值应单独使用。
    */
  typedef enum _ElectronicBillsType {
    /** @brief 电子凭证类型：未知。 */
    e_ElectronicUnknown  =  0,
    /** @brief 电子凭证类型：铁路电子客票开具方。 */
    e_ElectronicRAIIssuer  =  1,
    /** @brief 电子凭证类型：铁路电子客票接收方。 */
    e_ElectronicRAIReceiver  =  2,
    /** @brief 电子凭证类型：增值税电子普通发票开具方。 */
    e_ElectronicInvoiceOrdIssuer  =  3,
    /** @brief 电子凭证类型：增值税电子普通发票接收方 。 */
    e_ElectronicInvoiceOrdReceiver  =  4,
    /** @brief 电子凭证类型：增值税电子专用发票开具方。 */
    e_ElectronicInvoiceSpclIssuer  =  5,
    /** @brief 电子凭证类型：增值税电子专用发票接收方。 */
    e_ElectronicInvoiceSpclReceiver  =  6,
    /** @brief 电子凭证类型：银行电子回单开具方。 */
    e_ElectronicBkerIssuer  =  7,
    /** @brief 电子凭证类型：银行电子回单接收方。 */
    e_ElectronicBkerReceiver  =  8,
    /** @brief 电子凭证类型：银行电子对账单。 */
    e_ElectronicBkrs  =  9,
    /** @brief 电子凭证类型：数电票普通发票。 */
    e_ElectronicEinvOrd  =  10,
    /** @brief 电子凭证类型：数电票专用发票。 */
    e_ElectronicEinvSpcl  =  11,
    /** @brief 电子凭证类型：电子客票行程单开具方。 */
    e_ElectronicATRIssuer  =  12,
    /** @brief 电子凭证类型：电子客票行程单接收方。 */
    e_ElectronicATRReceiver  =  13,
    /** @brief 电子凭证类型：电子非税收入一般缴款书开具方。 */
    e_ElectronicNTREVIssuer  =  14,
    /** @brief 电子凭证类型：电子非税收入一般缴款书接收方。 */
    e_ElectronicNTREVReceiver  =  15,
    /** @brief 电子凭证类型：财政电子票据。 */
    e_ElectronicEFI  =  16
  } ElectronicBillsType;
  

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

  /**
   * @brief 构造函数，通过另一个附件集合对象。
   *
   * @param[in] other 另一个附件集合对象。
   */
  Attachments(const Attachments& other);

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

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

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

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

  /**
   * @brief 获取附件的数量。
   *
   * @return 附件的数量。
   */
  int GetAttachmentCount();

  /**
   * @brief 获取指定索引的附件对象。
   *
   * @param[in] index  指定的索引。有效范围：从0到(<i>count - 1</i>)。
   *                   <i>count</i>由函数 @link foxit::ofd::Attachments::GetAttachmentCount @endlink 返回。
   *
   * @return 指定索引的附件对象。
   */
  Attachment GetAttachment(int index);

  /**
   * @brief 通过ID获取附件对象。
   *
   * @param[in] index  指定的ID。
   *
   * @return 指定ID的附件对象。
   */
  Attachment GetAttachmentByID(foxit::uint32 id);

  /**
   * @brief 添加一个新的附件对象。
   *
   * @return 新的附件对象。
   */
  Attachment AddAttachment();

  /**
   * @brief 删除指定索引的附件对象。
   *
   * @param[in] index  指定的索引。有效范围：从0到(<i>count - 1</i>)。
   *                   <i>count</i>由函数 @link foxit::ofd::Attachments::GetAttachmentCount @endlink 返回。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool RemoveAttachment(int index);

  /**
   * @brief 删除所有附件对象。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool RemoveAllAttachments();

  /**
   * @brief 获取电子凭证的数量。
   *
   * @return 电子凭证的数量。
   */
  int GetElectronicBillsCount();

  /**
   * @brief 获取指定索引的电子凭证类型。
   *
   * @param[in] index  指定的索引。有效范围：从0到(<i>count - 1</i>)。
   *                   <i>count</i>由函数 @link foxit::ofd::Attachments::GetElectronicBillsCount @endlink 返回。
   *
   * @return 指定索引的电子凭证类型。
   */
  ElectronicBillsType GetElectronicBillsType(int index);

  /**
   * @brief 导出指定索引的电子凭证文件到指定路径。
   *
   * @param[in] index      指定的索引。有效范围：从0到(<i>count - 1</i>)。
   *                       <i>count</i>由函数 @link foxit::ofd::Attachments::GetElectronicBillsCount @endlink 返回。
   * @param[in] file_path  指定的文件路径。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool ExportElectronicBillsFile(int index, const String& file_path);

  /**
   * @brief 导出指定索引的电子凭证文件到指定路径。
   *
   * @param[in] index      指定的索引。有效范围：从0到(<i>count - 1</i>)。
   *                       <i>count</i>由函数 @link foxit::ofd::Attachments::GetElectronicBillsCount @endlink 返回。
   * @param[in] file_path  指定的文件路径。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool ExportElectronicBillsFile(int index, const WString& file_path);

  /**
   * @brief 获取附件目录扩展属性数量。
   *
   * @return 附件目录扩展属性数量。
   */
  int GetAttachmentDirectoryExtAttributeCount();

  /**
   * @brief 获取指定索引的附件目录扩展属性。
   *
   * @param[in] index 指定的索引。有效范围：从0到(<i>count - 1</i>)。
   *                  <i>count</i>由函数 @link foxit::ofd::Attachments::GetAttachmentDirectoryExtAttributeCount @endlink 返回。
   *
   * @return 指定索引的附件目录扩展属性对象。
   */
  Attachment GetAttachmentDirectoryExtAttribute(int index);

  /**
   * @brief 获取附件目录扩展信息，格式为xml。
   *
   * @return 附件目录扩展信息文件信息。
   */
  String GetAttachmentDirectoryExtInfoFile();

  /**
   * @brief 导出附件目录扩展信息到文件，格式为xml。
   *
   * @param[in] file_path  指定的文件路径。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool GetAttachmentDirectoryExtInfoFile(const String& file_path);

  /**
   * @brief 导出附件目录扩展信息到文件，格式为xml。
   *
   * @param[in] file_path  指定的文件路径。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool GetAttachmentDirectoryExtInfoFile(const WString& file_path);

  /**
   * @brief 通过文件设置附件目录扩展信息，格式为xml。
   *
   * @param[in] file_path  指定的文件路径。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool SetAttachmentDirectoryExtInfoFile(const String& file_path);

  /**
   * @brief 通过文件设置附件目录扩展信息，格式为xml。
   *
   * @param[in] file_path  指定的文件路径。
   *
   * @return <b>true</b> 表示成功，<b>false</b> 表示失败。
   */
  bool SetAttachmentDirectoryExtInfoFile(const WString& file_path);

  /**
   * @brief 获取附件目录对象。
   *
   * @return 附件目录对象。
   */
  AttachmentDirectory GetAttachmentDirectory();

  /**
   * @brief 创建附件目录对象。
   *
   * @return 附件目录对象。
   */
  AttachmentDirectory CreateAttachmentDirectory();

  explicit Attachments(FS_HANDLE handle);
};

}  // namespace ofd
}  // namespace foxit

#endif  // FS_OFD_ATTACHMENT_H_
