#ifndef FS_OFD_CUSTOM_SIGNATURE_H_
#define FS_OFD_CUSTOM_SIGNATURE_H_

#include "common/fs_common.h"

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

/** 此类表示和OFD自定义签名或签章相关的回调接口。 */
class SignatureCallback
{
 public:
   /** 析构函数 */
   virtual ~SignatureCallback() {}

   /**
    * @brief 获取签名或签章提供者名称。
    *
    * @return 提供者名称。
    */
   virtual String GetProviderName() = 0;

   /** 获取签名或签章提供者公司名称。
    *
    * @brief 获取签名或签章提供者公司名称。
    *
    * @return 公司名称。
   */
   virtual String GetCompany() = 0;

   /**
    * @brief 获取签名或签章版本号。
    *
    * @return 版本号。
    */
   virtual String GetVersion() = 0;

   /**
    * @brief 获取签名时间。
    *
    * @return 签名时间。
    */
   virtual String GetSignatureTime() = 0;

   /**
    * @brief 对数据进行摘要计算。
    *
    * @param[in]  data    待摘要计算的原始数据。
    * @param[in]  length  待摘要计算的原始数据的长度。
    *
    * @return 摘要值。
    */
   virtual String Digest(const void* data, int length) = 0;

   /**
    * @brief 获取摘要方法名称。
    *
    * @return 摘要方法名称。
    */
   virtual String GetDigestMethod() = 0;

   /**
    * @brief 对数据进行签名计算。
    *
    * @param[in]  data    待签名的原始数据。
    * @param[in]  length  待签名的原始数据的长度。
    *
    * @return 签名值。
    */
   virtual String Sign(const void* data, int length) = 0;

   /**
    * @brief 获取签名方法名称。
    *
    * @return 签名方法名。
    */
   virtual String GetSignMethod() = 0;

   /**
    * @brief 获取印章文件(Seal.esl)内容。
    *
    * @return 印章文件的内容。
    */
   virtual String GetSeal() = 0;

  /**
    * @brief 验证签名值。
    *
    * @param[in]  data                待验证的原始数据。
    * @param[in]  length              待验证的原始数据的长度。
    * @param[in]  sign_value          签名值。
    * @param[in]  sign_value_length   签名值的长度。
    *
    * @return <b>true</b>表示验证成功，<b>false</b>表示验证失败。
    */
   virtual bool Verify(const void* data, int length, const void* sign_value, int sign_value_length) = 0;
};

/** 此类表示和OFD自定义签名或签章相关的操作。 */
class CustomSignatureDoc FS_FINAL : public Base {
 public:
  /**
   * @brief 带参数的构造函数。
   *
   * @param[in] doc       OFD文档对象。
   * @param[in] callback  自定义签名或签章回调接口对象。
   */
  explicit CustomSignatureDoc(OFDDoc doc, SignatureCallback* callback);

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

  /**
   * @brief 构造函数，通过另一个OFD自定义签名或签章对象。
   *
   * @param[in] other 另一个OFD自定义签名或签章对象。
   */
  CustomSignatureDoc(const CustomSignatureDoc& other);

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

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

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

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

  /**
   * @brief 在多页相同位置对OFD文档进行自定义签名或签章。
   *
   * @param[in] page_scope  页面索引范围，从0开始。如下格式的字符串 "0-10,35,50-" 分别表示: 0~10页、35页、50页到最后一页。
                            "0-"，表示全部页面。
   * @param[in] position    签名或签章图像位置参数，详见 @link foxit::ofd::ofdseal::ImagePosition @endlink 。
                            此属性中的 @link foxit::ofd::ofdseal::ImagePosition::page_index @endlink 属性将不会生效。
   * @param[in] dest_file   签名或签章后保存的目标文件路径。
   * @param[in] proterties  签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithMultiPage(const String& page_scope, const ImagePosition& position, const String& dest_file, const PublicProperties& proterties = PublicProperties());

  /**
   * @brief 在多页相同位置对OFD文档进行自定义签名或签章。
   *
   * @param[in] page_scope  页面索引范围，从0开始。如下格式的字符串 "0-10,35,50-" 分别表示: 0~10页、35页、50页到最后一页。
                            "0-"，表示全部页面。
   * @param[in] position    签名或签章图像位置参数，详见 @link foxit::ofd::ofdseal::ImagePosition @endlink 。
                            此属性中的 @link foxit::ofd::ofdseal::ImagePosition::page_index @endlink 属性将不会生效。
   * @param[in] dest_file   签名或签章后保存的目标文件路径。
   * @param[in] proterties  签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithMultiPage(const String& page_scope, const ImagePosition& position, const WString& dest_file, const PublicProperties& proterties = PublicProperties());

  /**
   * @brief 在多页相同位置对OFD文档进行自定义签名或签章。
   *
   * @param[in] page_scope  页面索引范围，从0开始。如下格式的字符串 "0-10,35,50-" 分别表示: 0~10页、35页、50页到最后一页。
                            "0-"，表示全部页面。
   * @param[in] position    签名或签章图像位置参数，详见 @link foxit::ofd::ofdseal::ImagePosition @endlink 。
                            此属性中的 @link foxit::ofd::ofdseal::ImagePosition::page_index @endlink 属性将不会生效。
   * @param[in] file_writer 用户实现的 @link common::file::WriterCallback @endlink 对象，用于保存签名或签章后的文件。
   * @param[in] proterties  签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithMultiPage(const String& page_scope, const ImagePosition& position, foxit::common::file::WriterCallback* file_writer, const PublicProperties& proterties = PublicProperties());

  /**
   * @brief 在多页相同位置对OFD文档进行自定义签名或签章。
   *
   * @param[in] page_index_array  页面索引数组，从0开始。
   * @param[in] position          签名或签章图像位置参数，详见 @link foxit::ofd::ofdseal::ImagePosition @endlink 。
                                  此属性中的 @link foxit::ofd::ofdseal::ImagePosition::page_index @endlink 属性将不会生效。
   * @param[in] dest_file         签名或签章后保存的目标文件路径。
   * @param[in] proterties        签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithMultiPage(const foxit::Int32Array& page_index_array, const ImagePosition& position, const String& dest_file, const PublicProperties& proterties = PublicProperties());

  /**
   * @brief 在多页相同位置对OFD文档进行自定义签名或签章。
   *
   * @param[in] page_index_array  页面索引数组，从0开始。
   * @param[in] position          签名或签章图像位置参数，详见 @link foxit::ofd::ofdseal::ImagePosition @endlink 。
                                  此属性中的 @link foxit::ofd::ofdseal::ImagePosition::page_index @endlink 属性将不会生效。
   * @param[in] dest_file         签名或签章后保存的目标文件路径。
   * @param[in] proterties        签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithMultiPage(const foxit::Int32Array& page_index_array, const ImagePosition& position, const WString& dest_file, const PublicProperties& proterties = PublicProperties());

  /**
   * @brief 在多页相同位置对OFD文档进行自定义签名或签章。
   *
   * @param[in] page_index_array  页面索引数组，从0开始。
   * @param[in] position          签名或签章图像位置参数，详见 @link foxit::ofd::ofdseal::ImagePosition @endlink 。
                                  此属性中的 @link foxit::ofd::ofdseal::ImagePosition::page_index @endlink 属性将不会生效。
   * @param[in] file_writer       用户实现的 @link common::file::WriterCallback @endlink 对象，用于保存签名或签章后的文件。
   * @param[in] proterties        签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithMultiPage(const foxit::Int32Array& page_index_array, const ImagePosition& position, foxit::common::file::WriterCallback* file_writer, const PublicProperties& proterties = PublicProperties());

  /**
   * @brief 在跨页位置对OFD文档进行自定义签名或签章，即骑缝章。
   *
   * @param[in] position      跨页位置参数，详见 @link foxit::ofd::ofdseal::StraddlePosition @endlink 。
   * @param[in] width         签名或签章图像宽度。
   * @param[in] height        签名或签章图像高度。
   * @param[in] dest_file     签名或签章后保存的目标文件路径。
   * @param[in] proterties    签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithStraddle(const StraddlePosition& position, float width, float height, const String& dest_file, const PublicProperties& proterties = PublicProperties());

  /**
   * @brief 在跨页位置对OFD文档进行自定义签名或签章，即骑缝章。
   *
   * @param[in] position      跨页位置参数，详见 @link foxit::ofd::ofdseal::StraddlePosition @endlink 。
   * @param[in] width         签名或签章图像宽度。
   * @param[in] height        签名或签章图像高度。
   * @param[in] dest_file     签名或签章后保存的目标文件路径。
   * @param[in] proterties    签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithStraddle(const StraddlePosition& position, float width, float height, const WString& dest_file, const PublicProperties& proterties = PublicProperties());

  /**
   * @brief 在跨页位置对OFD文档进行自定义签名或签章，即骑缝章。
   *
   * @param[in] position      跨页位置参数，详见 @link StraddlePosition @endlink 。
   * @param[in] width         签名或签章图像宽度。
   * @param[in] height        签名或签章图像高度。
   * @param[in] file_writer   用户实现的 @link common::file::WriterCallback @endlink 对象，用于保存签名或签章后的文件。
   * @param[in] proterties    签名或签章的公共属性参数，默认值为空属性。
   *
   * @return <b>true</b>表示签名或签章成功，<b>false</b>表示签名或签章失败。
   */
  bool SignWithStraddle(const StraddlePosition& position, float width, float height, foxit::common::file::WriterCallback* file_writer, const PublicProperties& proterties = PublicProperties());

  explicit CustomSignatureDoc(FS_HANDLE handle);
};

/** 此类表示和OFD自定义签名或签章验证相关的操作。 */
class CustomVerify FS_FINAL : public Base {
 public:
  /** OFD签名或签章对象的自定义验证。
   *
   * @param[in] signature   签名或签章对象。
   * @param[in] callback    自定义签名或签章回调接口对象。
   */
  static bool Verify(Signature signature, SignatureCallback* callback);
};

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

#endif  // _BUILD_OFDSDK_
