#ifndef FS_OFD_Envelope_H_
#define FS_OFD_Envelope_H_

#include "common/fs_common.h"

/**
 * @brief Foxit 命名空间。
 *
 * @details Foxit PDF SDK 的所有定义和类都在此命名空间内定义。
 */
namespace foxit {
/**
 * @brief ofd 命名空间。
 */
namespace ofd {
/** 此类表示和OFD信封信息相关的操作。*/
class OFDEnvelopeInfo FS_FINAL : public Base {
 public:
  /**
    * @brief OFD信封加密类型定义枚举类型。
    *
    * @details 该枚举值应单独使用。
    */
  typedef enum _EnvelopeEncryptType {
    /** @brief 加密类型：RC4。 */
    e_EnvelopeEncryptTypeRC4 = 0,
    /** @brief 加密类型：AES128。 */
    e_EnvelopeEncryptTypeAES128 = 1,
    /** @brief 加密类型：AES192。 */
    e_EnvelopeEncryptTypeAES192 = 2,
    /** @brief 加密类型：AES256。 */
    e_EnvelopeEncryptTypeAES256 = 3,
    /** @brief 加密类型：SM4。 */
    e_EnvelopeEncryptTypeSM4 = 4
  } EnvelopeEncryptType;
  

  /**
   * @brief 构造函数。
   */
  OFDEnvelopeInfo();

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

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

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

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

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

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

  /**
   * @brief 获取标题。
   *
   * @return 标题。
   */
  WString GetTitle() const;

  /**
   * @brief 获取文件类型。
   *
   * @return 文件类型。
   */
  WString GetDocType() const;

  /**
   * @brief 获取文件描述。
   *
   * @return 文件描述。
   */
  WString GetDescription() const;

  /**
   * @brief 获取创建人。
   *
   * @return 创建人。
   */
  WString GetCreator() const;

  /**
   * @brief 获取创建时间。
   *
   * @return 创建时间。
   */
  foxit::DateTime GetCreateTime() const;

  /**
   * @brief 获取有效期限开始时间。
   *
   * @return 有效期限开始时间。
   */
  foxit::DateTime GetStartTime() const;

  /**
   * @brief 获取有效期限结束时间。
   *
   * @return 有效期限结束时间。
   */
  foxit::DateTime GetExpirationTime() const;

  /**
   * @brief 获取密码。
   *
   * @return 密码。
   */
  WString GetPassword() const;

  /**
   * @brief 获取用户权限。
   *
   * @return 用户权限。
   */
  WString GetPermission() const;

  /**
   * @brief 获取文件代码。
   *
   * @return 文件代码。
   */
  WString GetFileCode() const;

  /**
   * @brief 获取密码哈希值。
   *
   * @return 密码哈希值。
   */
  WString GetHashKey() const;

  /**
   * @brief 获取密码机密和证书加密标志位。
   *
   * @return 加密标志位。
   */
  WString GetFilter() const;

  /**
   * @brief 获取加密子标志位。
   *
   * @return 加密子标志位。
   */
  WString GetSubFilter() const;

  /**
   * @brief 获取加密类型。
   *
   * @return 加密类型。请参考从枚举 @link foxit::ofd::EnvelopeInfo::e_EnvelopeEncryptTypeRC4 @endlink 开始的值,
   *         这应该是这些值中的一个。
   */
  EnvelopeEncryptType GetCipher() const;

  /**
   * @brief 获取安全类型。
   *
   * @return 安全类型。
   */
  WString GetSecurityType() const;

  /**
   * @brief 获取加密类型。
   *
   * @return 加密类型。
   */
  WString GetCryptoType() const;

  /**
   * @brief 设置文件名称。
   *
   * @param[in] title 文件名称。
   *
   * @return 无。
   */
  void SetTitle(const WString& title);

  /**
   * @brief 设置文件类型。
   *
   * @param[in] doc_type 文件类型。
   *
   * @return 无。
   */
  void SetDocType(const WString& doc_type);

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

  /**
   * @brief 设置创建人。
   *
   * @param[in] creator 创建人。
   *
   * @return 无。
   */
  void SetCreator(const WString& creator);

  /**
   * @brief 设置创建时间。
   *
   * @param[in] create_time 创建时间。
   *
   * @return 无。
   */
  void SetCreateTime(const foxit::DateTime& create_time);

  /**
   * @brief 设置有效期限开始时间。
   *
   * @param[in] start_time 有效期限开始时间。
   *
   * @return 无。
   */
  void SetStartTime(const foxit::DateTime& start_time);

  /**
   * @brief 设置有效期限结束时间。
   *
   * @param[in] expiration_time 有效期限结束时间。
   *
   * @return 无。
   */
  void SetExpirationTime(const foxit::DateTime& expiration_time);

  /**
   * @brief 设置密码。
   *
   * @param[in] password 密码。
   *
   * @return 无。
   */
  void SetPassword(const WString& password);

  /**
   * @brief 设置用户权限。
   *
   * @param[in] permission 用户权限。
   *
   * @return 无。
   */
  void SetPermission(const WString& permission);

  /**
   * @brief 设置文件代码。
   *
   * @param[in] file_code 文件代码。
   *
   * @return 无。
   */
  void SetFileCode(const WString& file_code);

  /**
   * @brief 设置加密类型。
   *
   * @param[in] cipher 加密类型。请参考从枚举 @link foxit::ofd::EnvelopeInfo::e_EnvelopeEncryptTypeRC4 @endlink 开始的值,
   *                   这应该是这些值中的一个。
   *
   * @return 无。
   */
  void SetCipher(EnvelopeEncryptType cipher);

  explicit OFDEnvelopeInfo(FS_HANDLE handle);
};

/** 此类表示和OFD信封相关的操作。*/
class OFDEnvelope FS_FINAL : public CFX_Object {
 public:
  /**
   * @brief 获取信封文件信息。
   *
   * @param[in] input_envelope_file 信封文件路径。
   *
   * @return 信封文件信息对象。
   */
  static OFDEnvelopeInfo GetEnvelopeInfo(const WString& input_envelope_file);

  /**
   * @brief 信封文件密码验证。
   *
   * @param[in] password  信封文件密码。
   * @param[in] info      已获取的信封信息。
   *
   * @return <b>true</b> 表示密码验证成功，<b>false</b> 表示密码验证失败。
   */
  static bool VerifyPassword(const String& password, const OFDEnvelopeInfo& info);

  /**
   * @brief 信封密码加密。
   *
   * @param[in] info                  信封信息。
   * @param[in] input_ofd_file        输入ofd文件路径。
   * @param[in] output_envelope_file  输出信封文件路径。
   *
   * @return <b>true</b> 表示加密成功，<b>false</b> 表示加密失败。
   */
  static bool Encrypt(const OFDEnvelopeInfo& info, const WString& input_ofd_file, const WString& output_envelope_file);

  /**
   * @brief 信封文件解密。
   *
   * @param[in] password              信封文件密码。
   * @param[in] input_envelope_file   输入信封文件路径。
   * @param[in] output_ofd_file       输出ofd文件路径。
   *
   * @return <b>true</b> 表示解密成功，<b>false</b> 表示解密失败。
   *
   */
  static bool Decrypt(const String& password, const WString& input_envelope_file, const WString& output_ofd_file);
};

}  // namespace ofd
}  // namespace foxit

#endif  // FS_OFD_Envelope_H_
