#ifndef FS_OFD_SIGNATUE_H_
#define FS_OFD_SIGNATUE_H_

#include "common/fs_common.h"
#include "common/fs_image.h"

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

/** 此类表示操作OFD签名签章公共相关的信息。 */
class OperateSignatureInfo FS_FINAL : public Object {
 public:
  /**
   * @brief OFD操作签章模式枚举。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _SignatureOperationType {
    /** @brief 仅删除印章/签名信息, 不删除印章/签名图片。 */
    e_RemoveInfoOnly  =  0,
    /** @brief 删除印章/签名信息, 红章转黑章(即将彩色图转为灰度图)。 */
    e_ConvertToBlackImage  =  1,
    /** @brief 删除印章/签名信息, 印章/签名图片雾化。 */
    e_AtomizeImage  =  2,
    /** @brief 删除印章/签名信息, 印章/签名图片马赛克。 */
    e_MosaicImage  =  3,
    /** @brief 完全删除印章及印章图片。 */
    e_RemoveAll  =  4
  } SignatureOperationType;


  /**
   * @brief 带参数的构造函数。
   *
   * @param[in] operation_type            签章操作类型。请参考从 @link foxit::ofd::ofdseal::OperateSignatureInfo::e_RemoveInfoOnly @endlink 开始的值，
   *                                      这应该是这些值中的一个。
   * @param[in] atomize_horz_blur         横向高斯模糊。operation_type为e_AtomizeImage时起作用。
   * @param[in] atomize_vert_blur         纵向高斯模糊。operation_type为e_AtomizeImage时起作用。
   * @param[in] mosaic_vector_length      马赛克向量长度。operation_type为e_MosaicImage时起作用。
   */
  explicit OperateSignatureInfo(SignatureOperationType operation_type = e_RemoveInfoOnly, int atomize_horz_blur = 5, int atomize_vert_blur = 5, int mosaic_vector_length = 5) :
    operation_type(operation_type),
    atomize_horz_blur(atomize_horz_blur),
    atomize_vert_blur(atomize_vert_blur),
    mosaic_vector_length(mosaic_vector_length) {
  }

  /**
   * @brief 构造函数，通过另一个操作签名信息对象。
   *
   * @param[in] other 另一个操作签名信息对象。
   */
  OperateSignatureInfo(const OperateSignatureInfo& other) {
    this->operation_type = other.operation_type;
    this->atomize_horz_blur = other.atomize_horz_blur;
    this->atomize_vert_blur = other.atomize_vert_blur;
    this->mosaic_vector_length = other.mosaic_vector_length;
  }

  /**
   * @brief 赋值操作符。
   *
   * @param[in] other 另一个操作签名信息对象，其值将被赋给当前对象。
   *
   * @return 当前对象自身的引用。
   */
  OperateSignatureInfo& operator=(const OperateSignatureInfo& other) {
    this->operation_type = other.operation_type;
    this->atomize_horz_blur = other.atomize_horz_blur;
    this->atomize_vert_blur = other.atomize_vert_blur;
    this->mosaic_vector_length = other.mosaic_vector_length;
    return *this;
  }

  /**
   * @brief 设置值。
   *
   * @param[in] operation_type            签章操作类型。请参考从 @link foxit::ofd::ofdseal::OperateSignatureInfo::e_RemoveInfoOnly @endlink 开始的值，
   *                                      这应该是这些值中的一个。
   * @param[in] atomize_horz_blur         横向高斯模糊。operation_type为e_AtomizeImage时起作用。
   * @param[in] atomize_vert_blur         纵向高斯模糊。operation_type为e_AtomizeImage时起作用。
   * @param[in] mosaic_vector_length      马赛克向量长度。operation_type为e_MosaicImage时起作用。
   *
   * @return 无。
   */
  void Set(SignatureOperationType operation_type, int atomize_horz_blur, int atomize_vert_blur, int mosaic_vector_length) {
    this->operation_type = operation_type;
    this->atomize_horz_blur = atomize_horz_blur;
    this->atomize_vert_blur = atomize_vert_blur;
    this->mosaic_vector_length = mosaic_vector_length;
  }

  /**
   * @brief 签章操作类型。请参考从 @link foxit::ofd::ofdseal::OperateSignatureInfo::e_RemoveInfoOnly @endlink 开始的值，
   *       这应该是这些值中的一个。
   *
   */
  SignatureOperationType operation_type;

  /**
   * @brief 横向高斯模糊。operation_type为e_AtomizeImage时起作用。
   *
   */
  int atomize_horz_blur;

  /**
   * @brief 纵向高斯模糊。operation_type为e_AtomizeImage时起作用。
   *
   */
  int atomize_vert_blur;

  /**
   * @brief 马赛克向量长度。operation_type为e_MosaicImage时起作用。
   *
   */
  int mosaic_vector_length;
};

/** 此类表示验证OFD签章的扩展信息。 */
class VerifyExtendInfo FS_FINAL : public Object
{
 public:
  /**
   * @brief 带参数的构造函数。
   *
   * @param[in] application_name  调用验章功能的业务系统名称，必须为UTF-8编码。
   * @param[in] user_login        调用验章功能的业务系统用户账号，必须为UTF-8编码。
   * @param[in] file_name         进行验章的文件名称，必须为UTF-8编码。
   */
  explicit VerifyExtendInfo(const String& application_name = "", const String& user_login = "", const String& file_name = "") :
    application_name(application_name),
    user_login(user_login),
    file_name(file_name) {
  }

  /**
   * @brief 构造函数，通过另一个验证扩展信息对象。
   *
   * @param[in] other 另一个验证扩展信息对象。
   */
  VerifyExtendInfo(const VerifyExtendInfo& other) :
    application_name(other.application_name),
    user_login(other.user_login),
    file_name(other.file_name) {
  }

  /**
   * @brief 赋值操作符。
   *
   * @param[in] other 另一个验证扩展信息对象，其值将被赋给当前对象。
   *
   * @return 当前对象自身的引用。
   */
  VerifyExtendInfo& operator=(const VerifyExtendInfo& other) {
    this->application_name = other.application_name;
    this->user_login = other.user_login;
    this->file_name = other.file_name;
    return *this;
  }

  /**
   * @brief 设置值。
   *
   * @param[in] application_name  调用验章功能的业务系统名称，必须为UTF-8编码。
   * @param[in] user_login        调用验章功能的业务系统用户账号，必须为UTF-8编码。
   * @param[in] file_name         进行验章的文件名称，必须为UTF-8编码。
   *
   * @return 无。
   */
  void Set(const String& application_name, const String& user_login, const String& file_name) {
    this->application_name = application_name;
    this->user_login = user_login;
    this->file_name = file_name;
  }

  /**
   * @brief 调用验章功能的业务系统名称，必须为UTF-8编码。
   *
   */
  String application_name;

  /**
   * @brief 调用验章功能的业务系统用户账号，必须为UTF-8编码。
   *
   */
  String user_login;

  /**
   * @brief 进行验章的文件名称，必须为UTF-8编码。
   *
   */
  String file_name;
};

/** 此类表示OFD文档签名签章对象相关的操作。 */
class Signature : public Base {
 public:
  /**
   * @brief OFD文档签名类型枚举。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _SignatureType {
    /** @brief 默认类型。 */
    e_SignatureTypeDefault = 0,
    /** @brief 电子签章.。*/
    e_SignatureTypeSeal = 1,
    /** @brief 证书签名.。*/
    e_SignatureTypeSign = 2,
    /** @brief 时间戳签名。 */
    e_SignatureTypeTimeStamp = 3
  } SignatureType;

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

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

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

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

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

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

  /**
   * @brief 获取签名类型。
   *
   * @return 签名类型。请参考从 @link foxit::ofd::ofdseal::SignatureType::e_SignatureTypeDefault @endlink 开始的值，这应该是这些值中的一个。
   *         应该是这些值中的一个。
   */
  SignatureType GetType();

  /**
   * @brief 获取提供者名称。
   *
   * @return 提供者名称。
   */
  WString GetProviderName();

  /**
   * @brief 获取公司名称。
   *
   * @return 公司名称。
   */
  WString GetCompany();

  /**
   * @brief 获取签名或签章版本。
   *
   * @return 签名或签章版本。
   */
  WString GetVersion();

  /**
   * @brief 获取摘要算法名称。
   *
   * @return 摘要算法名称。
   */
  WString GetDigestMethod();

  /**
   * @brief 获取签名算法名称。
   *
   * @return 签名算法名称。
   */
  WString GetSignMethod();

  /**
   * @brief 获取验证结果详细信息，只返回错误信息。
   *
   * @return 验证结果详细信息。
   */
  WString GetVerifyMessage();

  /**
   * @brief 对OFD文档内的签名或签章进行操作。
   *
   * @param[in] info  操作签名信息参数。
   *
   * @return <b>true</b> 表示操作成功，<b>false</b> 表示操作失败。
   */
  bool Operate(const foxit::ofd::ofdseal::OperateSignatureInfo& info);

  explicit Signature(FS_HANDLE handle);
};

/** 此类表示OFD文档签章对象相关的操作。 */
class SealSignature FS_FINAL : public Signature {
 public:
  /**
   * @brief 构造函数，从现有@link foxit::ofd::ofdseal::Signature @endlink对象。
   * @param[in] object Signature对象。
                       此对象必须是一个有效的对象，并且其类型必须是@link foxit::ofd::ofdseal::SignatureType::e_SignatureTypeSeal @endlink，否则构造函数将抛出异常。
   */
  explicit SealSignature(Signature object);

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

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

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

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

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

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

  /**
   * @brief 获取电子印章ID。
   *
   * @return 电子印章ID。
   */
  WString GetSealId();

  /**
   * @brief 获取电子印章版本。
   *
   * @return 电子印章版本。
   */
  WString GetSealVersion();

  /**
   * @brief 获取电子印章供应商ID。
   *
   * @return 电子印章供应商ID。
   */
  WString GetSealVenderId();

  /**
   * @brief 获取电子印章类型。
   *
   * @return 电子印章类型。
   */
  WString GetSealType();

  /**
   * @brief 获取电子印章名称。
   *
   * @return 电子印章名称。
   */
  WString GetSealName();

  /**
   * @brief 获取电子印章签章者证书信息。
   *
   * @return 电子印章签章者证书信息。
   */
  String GetSealSignerCertInfo();

  /**
   * @brief 获取电子印章有效起始时间。
   *
   * @return 电子印章有效起始时间。
   */
  WString GetSealValidStartTime();

  /**
   * @brief 获取电子印章有效截止时间。
   *
   * @return 电子印章有效截止时间。
   */
  WString GetSealValidEndTime();
  /**
   * @brief 获取电子印章签章时间。
   *
   * @return 电子印章签章时间。
   */
  WString GetSealSignedDate();

  /**
   * @brief 获取电子印章签章算法。
   *
   * @return 电子印章签章算法。
   */
  WString GetSealSignMethod();

  /**
   * @brief 获取电子印章图片。
   *
   * @return 图像对象。详见 @link foxit::common::Bitmap @endlink 。
   */
  foxit::common::Bitmap GetImage();

  /**
   * @brief 验证签章的有效性。
   *
   * @param[in] online  是否进行在线验证。
   *                    <b>true</b> 表示在线验证，<b>false</b> 表示离线验证。默认值为 <b>false</b>。
   *
   * @return <b>true</b> 表示验证成功，<b>false</b> 表示验证失败。
   */
  bool Verify(bool online = false);

  /**
   * @brief 使用指定的电子印章验证签章的有效性。
   *
   * @param[in] oes      电子印章库对象。详见 @link foxit::ofd::ofdseal::Oes @endlink 。
   * @param[in] online   是否进行在线验证。
   *                     <b>true</b> 表示在线验证，<b>false</b> 表示离线验证。默认值为 <b>false</b>。
   *
   * @return <b>true</b> 表示验证成功，<b>false</b> 表示验证失败。
   */
  bool VerifyWithOes(const Oes& oes, bool online = false);

  /**
   * @brief 不依赖电子印章库验证签章的有效性。
   *
   * @param[in] online  是否进行在线验证。
   *                    <b>true</b> 表示在线验证，<b>false</b> 表示离线验证。默认值为 <b>false</b>。
   *
   * @return <b>true</b> 表示验证成功，<b>false</b> 表示验证失败。
   */
  bool VerifyWithoutOes(bool online = false);

  /**
   * @brief 使用扩展信息验证签章的有效性。
   *
   * @param[in] extend_info  验证扩展信息参数。详见 @link foxit::ofd::ofdseal::VerifyExtendInfo @endlink 。
   *                         必须加载对应的电子印章库，否则验证将失败。
   * @param[in] online       是否进行在线验证。
   *                         <b>true</b> 表示在线验证，<b>false</b> 表示离线验证。默认值为 <b>false</b>。
   *
   * @return <b>true</b> 表示验证成功，<b>false</b> 表示验证失败。
   */
  bool VerifyEx(const foxit::ofd::ofdseal::VerifyExtendInfo& extend_info, bool online = false);

  /**
   * @brief 导出公钥证书文件。
   *
   * @param[in] file_path  公钥证书文件保存的目标路径。
   *
   * @return <b>true</b>表示导出成功，<b>false</b>表示导出失败。
   */
  bool ExportPublicCertificateFile(const String& file_path);

  /**
   * @brief 导出公钥证书文件。
   *
   * @param[in] file_path  公钥证书文件保存的目标路径。
   *
   * @return <b>true</b>表示导出成功，<b>false</b>表示导出失败。
   */
  bool ExportPublicCertificateFile(const WString& file_path);

  /**
   * @brief 导出公钥证书文件。
   *
   * @param[in] writer_callback  用户实现的 @link common::file::WriterCallback @endlink 对象，用于保存公钥证书文件。
   *
   * @return <b>true</b>表示导出成功，<b>false</b>表示导出失败。
   */
  bool ExportPublicCertificateFile(foxit::common::file::WriterCallback* writer_callback);

  explicit SealSignature(FS_HANDLE handle);
};

/** 此类表示OFD文档签名对象相关的操作。 */
class SignSignature FS_FINAL : public Signature {
 public:
  /**
   * @brief 构造函数，从现有@link foxit::ofd::ofdseal::Signature @endlink对象。
   * @param[in] object Signature对象。
                       此对象必须是一个有效的对象，并且其类型必须是@link foxit::ofd::ofdseal::SignatureType::e_SignatureTypeSign @endlink，否则构造函数将抛出异常。
   */
  explicit SignSignature(Signature object);

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

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

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

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

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

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

  /**
   * @brief 验证签名的有效性。
   *
   * @return <b>true</b> 表示验证成功，<b>false</b> 表示验证失败。
   */
  bool Verify();

  /**
   * @brief 导出公钥证书文件。
   *
   * @param[in] file_path  公钥证书文件保存的目标路径。
   *
   * @return <b>true</b>表示导出成功，<b>false</b>表示导出失败。
   */
  bool ExportPublicCertificateFile(const String& file_path);

  explicit SignSignature(FS_HANDLE handle);
};

}  // namespace ofdseal
}  // namespace ofd
}  // namespace foxit

#endif  // _BUILD_OFDSDK_
