#ifndef FS_OFD_TEXTOBJECT_H_
#define FS_OFD_TEXTOBJECT_H_

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

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

/** 文本对象字符信息结构。 */
class CharInfo FS_FINAL : public Object {
 public:
  /**
   * @brief 构造函数。
   */
  CharInfo() :
    charcode(0),
    x(0.0f),
    y(0.0f) {
  }
  /**
   * @brief 带参数的构造函数。
   *
   * @param[in] charcode        字符码。文字的UNICODE编码值。
   * @param[in] x               x轴坐标点，左下角点。坐标系为OFD坐标系。
   * @param[in] y               y轴坐标点，左下角点。坐标系为OFD坐标系。
   */
  CharInfo(foxit::uint32 charcode, float x, float y) :
    charcode(charcode),
    x(x),
    y(y){
  }

  /**
   * @brief 用另一个字符信息的构造函数。
   *
   * @param[in] other  另一个字符信息对象。
   */
  CharInfo& operator=(const CharInfo& other) {
    charcode = other.charcode;
    x = other.x;
    y = other.y;

    return *this;
  }

  /**
   * @brief 设置值。
   *
   * @param[in] charcode    字符码。文字的UNICODE编码值。
   * @param[in] x           x轴坐标点，左下角点。坐标系为OFD坐标系。
   * @param[in] y           y轴坐标点，左下角点。坐标系为OFD坐标系。
   *
   * @return 无。
   */
  void Set(foxit::uint32 charcode, float x, float y) {
    this->charcode = charcode;
    this->x = x;
    this->y = y;
  }

  /** @brief 字符码。文字的UNICODE编码值。*/
  foxit::uint32 charcode;

  /** @brief x轴坐标点，左下角点。坐标系为OFD坐标系。*/
  float x;

  /** @brief y轴坐标点，左下角点。坐标系为OFD坐标系。*/
  float y;
};

/** @brief 这个类代表 @link CharInfo @endlink 数组。 */
FSDK_DEFINE_ARRAY(CharInfoArray, CharInfo)

/** 此类表示和OFD文本对象相关的方法。*/
class OFDTextObject FS_FINAL : public OFDGraphicsObject {
 public:
  /**
   * @brief OFD文字阅读方向定义枚举类型。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _ReadDirectionType {
    /** @brief 阅读方向: 从左到右。 */
    e_ReadDirectionLeftToRight = 0,
    /** @brief 阅读方向: 从上到下。 */
    e_ReadDirectionTopToBottom = 1,
    /** @brief 阅读方向: 从右到左。 */
    e_ReadDirectionRightToLeft = 2,
    /** @brief 阅读方向: 从下到上。*/
    e_ReadDirectionBottomToTop = 3
  } ReadDirectionType;
  
  /**
   * @brief OFD文字字符方向定义枚举类型。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _CharDirectionType {
    /** @brief 字符方向: 正常。 */
    e_CharDirectionNormal = 0,
    /** @brief 字符方向: 向右。 */
    e_CharDirectionRight = 1,
    /** @brief 字符方向: 向上。 */
    e_CharDirectionBottom = 2,
    /** @brief 字符方向: 向左。 */
    e_CharDirectionLeft = 3
  } CharDirectionType;
  

  /**
   * @brief  构造函数，从现有@link foxit::ofd::graphics::OFDGraphicsObject @endlink对象。
   * @param[in] object OFDGraphicsObject对象。
                       此对象必须是一个有效的对象，并且其类型必须是@link foxit::ofd::graphics::OFDGraphicsObject::e_ObjectTypeText @endlink，否则构造函数将抛出异常。
   */
  explicit OFDTextObject(OFDGraphicsObject object);

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

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

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

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

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

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

  /**
   * @brief 获取文本对象的字体名称。
   *
   * @return 字体名称值。
   */
  WString GetFontName();

  /**
   * @brief 获取文本对象的字体大小。
   *
   * @return 字体大小值。
   */
  float GetFontSize();

  /**
   * @brief 判断文本对象是否填充。
   *
   * @return  <b>true</b> 表示填充，<b>false</b> 表示不填充。
   */
  bool IsFill();

  /**
   * @brief 判断文本对象是否勾边。
   *
   * @return  <b>true</b> 表示描边，<b>false</b> 表示不描边。
   */
  bool IsStroke();

  /**
   * @brief 获取文本对象的水平缩放。
   *
   * @return 水平缩放值。
   */
  float GetHScale();

  /**
   * @brief 获取文本对象的阅读方向。
   *
   * @return 阅读方向值。请参考从 @link foxit::ofd::graphics::OFDTextObject::e_ReadDirectionLeftToRight @endlink 开始的值，
   *         应该是这些值中的一个。
   */
  ReadDirectionType GetReadDirection();

  /**
   * @brief 获取文本对象的字符方向。
   *
   * @return 字符方向值。请参考从 @link foxit::ofd::graphics::OFDTextObject::e_CharDirectionNormal @endlink 开始的值，
   *         应该是这些值中的一个。
   */
  CharDirectionType GetCharDirection();

  /**
   * @brief 获取文本对象的粗细度。
   *
   * @return 粗细度值。
   */
  int GetWeight();

  /**
   * @brief 判断文本对象是否是斜体。
   *
   * @return true 斜体， false非斜体。
   */
  bool IsItalic();

  /**
   * @brief 获取文本对象的字符信息。
   *
   * @return 字符信息数组。
   */
  CharInfoArray GetCharInfo();

  /**
   * @brief 插入一段新的文本内容。
   *
   * @param[in] text              文本内容。
   * @param[in] x_pos             文字起始点x坐标（相对于图元对象boundary起始点的x坐标，单位mm）。
   * @param[in] y_pos             文字起始点y坐标（相对于图元对象boundary起始点的y坐标，单位mm）。
   * @param[in] calculate_width   是否根据文本内容计算并设置文本对象的宽度值，true表示计算，false表示不计算。
   *
   * @return 无。
   */
  void InsertText(const String& text, float x_pos, float y_pos, bool calculate_width = true);

  /**
   * @brief 修改文本对象的文本内容。
   *
   * @param[in] text              文本内容。
   *
   * @return 无。
   */
  void ModifyText(const String& text);

  /**
   * @brief 为文本对象添加下划线。
   *
   * @return 无。
   */
  void AddUnderline();

  /**
   * @brief 设置字体名称。
   *
   * @param[in] font_name         字体名称。
   *
   * @return 无。
   */
  void SetFontName(const WString& font_name);

  /**
   * @brief 设置文本对象的字体大小。
   *
   * @param[in] font_size         字体大小值。
   *
   * @return 无。
   */
  void SetFontSize(float font_size);

  /**
   * @brief 设置文本对象的水平缩放。
   *
   * @param[in] scale             设定的水平缩放值。
   *
   * @return 无。
   */
  void SetHScale(float scale);

  /**
   * @brief 设置文本对象的阅读方向。
   *
   * @param[in] type              设定的阅读方向值。请参考从 @link foxit::ofd::graphics::OFDTextObject::e_ReadDirectionLeftToRight @endlink 开始的值，
   *                              应该是这些值中的一个。
   *
   * @return 无。
   */
  void SetReadDirection(ReadDirectionType type);

  /**
   * @brief 设置文本对象的字符方向。
   *
   * @param[in] type              设定的字符方向值。请参考从 @link foxit::ofd::graphics::OFDTextObject::e_CharDirectionNormal @endlink 开始的值，
   *                              应该是这些值中的一个。
   *
   * @return 无。
   */
  void SetCharDirection(CharDirectionType type);

  /**
   * @brief 设置文本对象的粗细度。
   *
   * @param[in] weight        设定的粗细度值(可选取值为100,200,300,400,500,600,700,800,900,默认值为400,取值为其它值时按照默认值处理)。
   *
   * @return 无。
   */
  void SetWeight(int weight);

  /**
   * @brief 设置文本对象的斜体。
   *
   * @param[in] italic        设置为true为斜体，false为非斜体。
   *
   * @return 无。
   */
  void SetItalic(bool italic);

  /**
   * @brief 设置文本对象的字符信息。
   *
   * @param[in] char_infos    字符信息数组。
   * @param[in] x             字符起始点x坐标（相对于图元对象boundary起始点的x坐标，单位mm）。
   * @param[in] y             字符起始点y坐标（相对于图元对象boundary起始点的y坐标，单位mm）。
   *
   * @return 无。
   */
  void SetCharInfos(const foxit::UInt32Array& char_infos, float x, float y);

  /**
   * @brief 设置文本对象的字符信息(文字块)。
   *
   * @param[in] textpieceinfos   文字块信息对象。
   *
   * @return 无。
   */
  void SetTextPieceInfos(const foxit::ofd::TextPieceInfo& text_piece_info);

  /**
   * @brief 获取文本对象的Layout对象。
   *
   * @return 文本对象的Layout对象。
   */
  TextLayout GetTextLayout();

  explicit OFDTextObject(FS_HANDLE handle);
};

/** 此类表示和OFD文本布局对象相关的方法。*/
class TextLayout FS_FINAL : public Base {
 public:
  /**
   * @brief 文字Layout对象的水平对齐方式枚举。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _LayoutHAlignment {
    /** @brief 水平左对齐。 */
    e_LayoutHLeft = 0,
    /** @brief 水平中间对齐。 */
    e_LayoutHCenter = 1,
    /** @brief 水平右对齐。 */
    e_LayoutHRight = 2
  } LayoutHAlignment;
  
  /**
   * @brief 文字Layout对象的垂直对齐方式枚举。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _LayoutVAlignment {
    /** @brief 垂直上对齐。 */
    e_LayoutVTop = 0,
    /** @brief 垂直中间对齐。 */
    e_LayoutVCenter = 1,
    /** @brief 垂直底部对齐。 */
    e_LayoutVBottom = 2
  } LayoutVAlignment;
  

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

  /**
   * @brief 构造函数，通过另一个OFD文本布局对象。
   *
   * @param[in] other  另一个OFD文本布局对象。
   */
  TextLayout(const TextLayout& other);

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

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

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

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

  /**
   * @brief 获取文本对象结束位置相对于boundary在x方向上的偏移量。（富文本排版）
   *
   * @return 偏移量。
   *
   */
  float GetTextEndOffsetX();

  /**
   * @brief 获取文本对象结束位置相对于boundary在y方向上的偏移量。（富文本排版）
   *
   * @return 偏移量。
   *
   */
  float GetTextEndOffsetY();

  /**
   * @brief 设置文本内容。
   *
   * @param[in] text              文本内容。
   *
   * @return 无。
   */
  void SetText(const WString& text);

  /**
   * @brief 设置文字旋转角度。
   *
   * @param[in] rotation          旋转角度。
   *
   * @return 无。

   */
  void SetRotation(foxit::common::Rotation rotation);

  /**
   * @brief 设置字体名称。
   *
   * @param[in] font_name         字体名称。
   *
   * @return 无。
   */
  void SetFontName(const WString& font_name);

  /**
   * @brief 设置备选字体名称。
   *
   * @param[in] font_name         备选字体名称。
   *
   * @return 无。
   */
  void SetSubFontName(const WString& font_name);

  /**
   * @brief 设置字体粗细属性。
   *
   * @param[in] weight            字体粗细值。
   *
   * @return 无。
   */
  void SetWeight(int weight);

  /**
   * @brief 设置斜体属性。
   *
   * @param[in] italic            是否斜体。
   *
   * @return 无。
   */
  void EnableItalic(bool italic);

  /**
   * @brief 添加下划线。
   *
   * @return 无。
   */
  void AddUnderline();

  /**
   * @brief 设置最大字体大小。（富文本排版）
   *
   * @param[in] font_size         富文本字体大小值。
   *
   * @return 无。
   */
  void SetRTFFontSize(float font_size);

  /**
   * @brief 设置水平是否两端对齐。
   *
   * @param[in] set               水平是否两端对齐。
   *
   * @return 无。
   */
  void EnableJustifyX(bool set);

  /**
   * @brief 设置垂直是否两端对齐。
   *
   * @param[in] set               垂直是否两端对齐。
   *
   * @return 无。
   */
  void EnableJustifyY(bool set);

  /**
   * @brief 设置每行字符数。
   *
   * @param[in] num               每行字符数值。
   *
   * @return 无。
   */
  void SetLineCharNumer(int num);

  /**
   * @brief 设置每行字节数。
   *
   * @param[in] num               每行字节数值。
   *
   * @return 无。
   */
  void SetLineBitNumber(int num);

  /**
   * @brief 设置行间距。
   *
   * @param[in] space             行间距值
   *
   * @return 无。
   */
  void SetLineSpace(float space);

  /**
   * @brief 设置换行符。
   *
   * @param[in] line_break        换行符字符串。
   *
   * @return 无。
   */
  void SetLineBreak(const String& line_break);

  /**
   * @brief 设置是否自动调整大小。
   *
   * @param[in] auto_size 是否自动调整大小。<b>true</b>表示自动调整大小,</b>false</b>表示不自动调整。
   *
   * @return 无。
   */
  void EnableAutoSize(bool auto_size);

  /**
   * @brief 设置是否垂直排版。
   *
   * @param[in] set               是否垂直排版。<b>true</b>表示垂直排版,</b>false</b>表示不垂直排版。
   *
   * @return 无。
   */
  void EnableVertical(bool vertical);

  /**
   * @brief 设置字体大小。
   *
   * @param[in] font_size         字体大小值。
   *
   * @return 无。
   */
  void SetFontSize(float font_size);

  /**
   * @brief 设置水平对齐方式。
   *
   * @param[in]  align            水平对齐方式。请参考从 @link foxit::ofd::graphics::OFDTextLayout::e_LayoutHLeft @endlink 开始的值，
   *                              应该是这些值中的一个。
   *
   * @return 无。
   */
  void SetHAlignment(LayoutHAlignment align);

  /**
   * @brief 设置垂直对齐方式。
   *
   * @param[in] align             垂直对齐方式。请参考从 @link foxit::ofd::graphics::OFDTextLayout::e_LayoutVTop @endlink 开始的值，
   *                              应该是这些值中的一个。
   *
   * @return 无。
   */
  void SetVAlignment(LayoutVAlignment align);

  /**
   * @brief 设置是否需要折行。
   *
   * @param[in] set               是否需要折行。true 是，false 否
   *
   * @return 无。
   */
  void EnableMultiline(bool set);

  /**
   * @brief 更新Layout文本对象布局。
   *
   * @return 无。
   */
  void Update();

  explicit TextLayout(FS_HANDLE handle);
};

}  // namespace graphics
}  // namespace ofd
}  // namespace foxit

#endif  // FS_OFD_TEXTOBJECT_H_
