#ifndef FS_OFD_ANNOT_H_
#define FS_OFD_ANNOT_H_

#include "common/fs_common.h"

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

/** 此类表示和OFD标注对象相关的方法 */
class Annot FS_FINAL : public Base {
 public:
  /**
    * @brief OFD标注类型定义枚举类型.
    *
    * @details 该枚举值应单独使用.
    */
  typedef enum _AnnotType {
    /** @brief 标注类型：未知。 */
    e_AnnotTypeUnknown   =  0,
    /** @brief 标注类型：链接。 */
    e_AnnotTypeLink  =  1,
    /** @brief 标注类型：路径。 */
    e_AnnotTypePath  =  2,
    /** @brief 标注类型：高亮。 */
    e_AnnotTypeHighlight  =  3,
    /** @brief 标注类型：印章。 */
    e_AnnotTypeStamp  =  4,
    /** @brief 标注类型：水印。 */
    e_AnnotTypeWatermark  =  5,
    /** @brief 标注类型：控件。 */
    e_AnnotTypeWidget  =  6
  } AnnotType;
  

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

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

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

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

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

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

  /**
   * @brief 获取标注外观中的图元对象数量。
   *
   * @return 标注外观中的图元对象数量。
   */
  int GetAppearanceObjectCount();

  /**
   * @brief 获取标注外观中的图元对象。
   *
   * @param[in] index   标注外观中的图元对象索引号。有效范围：从0到(<i>count</i>-1)。
   *                     <i>count</i> 由函数 @link Annot::GetAppearanceObjectCount @endlink 返回。
   *
   * @return 标注外观对象。
   */
  graphics::OFDGraphicsObject GetAppearanceObject(int index);

  /**
   * @brief 获取标注类型。
   *
   * @return 标注类型。请参考从 @link foxit::ofd::Annot::e_AnnotTypeUnknown @endlink 开始的值，
   *         应该是这些值中的一个。
   */
  AnnotType GetType();

  /**
   * @brief 获取标注外接矩形框。
   *
   * @return 外接矩形框。坐标系为OFD坐标系。
   */
  foxit::RectF GetBoundary();

  /**
   * @brief 获取标注子类型。
   *
   * @return 子类型。
   */
  String GetSubtype();

  /**
   * @brief 获取标注创建者。
   *
   * @return 创建者。
   */
  String GetCreator();

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

  /**
   * @brief 添加标注外观图元对象。
   *
   * @param[in] type  图元对象类型。请参考从 @link foxit::ofd::graphics::OFDGraphicsObject::e_ObjectTypeUnknown @endlink 开始的值，
   *                  应该是这些值中的一个。
   *
   * @return 新添加的图元对象。
   */
  graphics::OFDGraphicsObject AddAppearanceObject(graphics::OFDGraphicsObject::ObjectType type);

  /**
   * @brief 添加标注外观块图元对象。
   *
   * @return 新添加的块图元对象。
   */
  graphics::OFDGraphicsObject AddBlockAppearanceObject();

  /**
   * @brief 设置标注外接矩形框。
   *
   * @param[in] rect  外接矩形框。坐标系为OFD坐标系。
   *
   * @return 无。
   */
  void SetBoundary(const foxit::RectF& rect);

  /**
   * @brief 设置标注子类型。
   *
   * @param[in] subtype  子类型。
   *
   * @return 无。
   */
  void SetSubtype(const String& subtype);

  /**
   * @brief 设置标注创建者。
   *
   * @param[in] creator  创建者。
   *
   * @return 无。
   */
  void SetCreator(const String& creator);

  /**
   * @brief 设置标注最后修改日期时间。
   *
   * @param[in] date_time  最后修改日期时间。
   *
   * @return 无。
   */
  void SetLastModDate(const foxit::DateTime& date_time);

  /**
   * @brief 设置链接URI。
   *
   * @param[in] uri  链接URI。
   *
   * @return 无。
   */
  void SetLinkUri(const String& uri);

  /**
   * @brief 判断标注是否可打印。
   *
   * @return <b>true</b>表示可打印，<b>false</b>表示不可打印。
   */
  bool IsPrintable();

  /**
   * @brief 设置标注是否可打印。
   *
   * @param[in] printable 是否可打印。
   *
   * @return 无。
   */
  void EnablePrintable(bool printable);

  /**
   * @brief 判断标注是否可见。
   *
   * @return <b>true</b>表示可见，<b>false</b>表示不可见。
   */
  bool IsVisible();

  /**
   * @brief 设置标注是否可见。
   *
   * @param[in] visible 是否可见。
   *
   * @return 无。
   */
  void EnableVisible(bool visible);

  /**
  * @brief 判断标注是否只读。
  *
  * @return <b>true</b>表示只读，<b>false</b>表示非只读。
  */
  bool IsReadOnly();

  /**
   * @brief 设置标注是否只读。
   *
   * @param[in] read_only 是否只读。
   *
   * @return 无。
   */
  void EnableReadOnly(bool read_only);

  /**
   * @brief 获取标注的动作集合。
   *
   * @return 动作集合对象。
   */
  Actions GetActions();

  explicit Annot(FS_HANDLE handle);
};

/** 此类表示和OFD标注组合对象相关的方法 */
class AnnotCombination FS_FINAL : public Base {
 public:
  /**
   * @brief 构造函数。
   */
  AnnotCombination();

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

  /**
   * @brief 构造函数，通过另一个OFD标注组合对象。
   *
   * @param[in] other  另一个OFD标注组合对象。
   */
  AnnotCombination(const AnnotCombination& other);

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

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

  /**
   * @brief 不相等操作符。
   *
   * @param[in] other  另一个OFD标注组合对象。此函数将检查当前对象是否不等于这个对象。
   *
   * @return <b>true</b> 表示不相等，<b>false</b> 表示相等。
   */
  bool operator != (const AnnotCombination& 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 AddAnnotFile(const String& file_path);

  /**
   * @brief 添加标注文件。
   *
   * @param[in] file_path  标注文件路径。
   *
   * @return <b>true</b>表示添加成功，<b>false</b>表示添加失败。
   */
  bool AddAnnotFile(const WString& file_path);

  /**
   * @brief 添加标注文件。
   *
   * @param[in] buf       标注文件内存缓冲区指针。
   * @param[in] buf_len   标注文件内存缓冲区大小。
   *
   * @return <b>true</b>表示添加成功，<b>false</b>表示添加失败。
   */
  bool AddAnnotFile(const void* buf, size_t buf_len);

  /**
   * @brief 添加标注文件。
   *
   * @param[in] file_reader  用户实现的 @link common::file::ReaderCallback @endlink 对象，用于加载标注文件。
   *
   * @return <b>true</b>表示添加成功，<b>false</b>表示添加失败。
   */
  bool AddAnnotFile(foxit::common::file::ReaderCallback* file_reader);

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

  /**
   * @brief 导出标注组合到新的ofd文件。
   *
   * @param[in] file_path  导出标注文件路径。
   *
   * @return <b>true</b>表示导出成功，<b>false</b>表示导出失败。
   */
  bool ExportToFile(const WString& file_path);

  /**
   * @brief 导出新的标注组合ofd文件到内存缓冲区。
   *
   * @return 标注组合内存缓冲区。
   */
  String ExportToFile();

  /**
   * @brief 导出标注组合到新的ofd文件。
   *
   * @param[in] file_writer  用户实现的 @link common::file::WriterCallback @endlink 对象，用于保存标注组合文件。
   *
   * @return <b>true</b>表示导出成功，<b>false</b>表示导出失败。
   */
  bool ExportAnnotFile(foxit::common::file::WriterCallback* file_writer);

  explicit AnnotCombination(FS_HANDLE handle);
};

}  // namespace ofd
}  // namespace foxit

#endif  // FS_OFD_ANNOT_H_
