#ifndef FS_OFD_GRAPHICS_OBJECT_H_
#define FS_OFD_GRAPHICS_OBJECT_H_

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

/**
 * @brief Foxit 命名空间。
 *
 * @details Foxit PDF SDK 的所有定义和类都在此命名空间内定义。
 */
namespace foxit {
/**
 * @brief ofd 命名空间。
 */
namespace common {
class Image;
};
namespace ofd {
class Actions;
/**
 * @brief ofd graphics 命名空间。
 */
namespace graphics {
/** 此类代表了边框信息。 */
class BorderInfo FS_FINAL : public Object {
 public:
  /**
   * @brief OFD线端点样式枚举。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _LineCapMode {
    /**
     * @brief 平头端盖。描边在路径的端点处被切断。路径末端之外没有投影。
     */
    e_LineCapButt = 0,
    /**
     * @brief 圆头端盖。在端点周围绘制一个直径等于线宽的半圆弧并填充。
     */
    e_LineCapRound = 1,
    /**
     * @brief 投影方形端盖。描边在路径端点之外继续延伸等于线宽一半的距离，并被切断。
     */
    e_LineCapSquare = 2
  } LineCapMode;
  

  /**
   * @brief 构造函数。
   */
  BorderInfo()
    :line_width(0.0f)
    ,line_cap(e_LineCapButt)
    ,color(0)
    ,h_radius(0.0f)
    ,v_radius(0.0f)
    ,dash_offset(0.0f) {}

  /**
   * @brief 带参数的构造函数。
   *
   * @param[in] line_width        边框宽度，以点为单位。这应该是一个非负值。
   * @param[in] line_cap          线端点样式。请参考从 @link foxit::ofd::graphics::BorderInfo::e_LineCapButt @endlink 开始的值，
   *                              应该是这些值中的一个。
   * @param[in] color             边框颜色。
   * @param[in] h_radius          横向圆角半径。
   * @param[in] v_radius          纵向圆角半径。
   * @param[in] dash_offset       虚线偏移量。
   * @param[in] dash_pattern      虚线模式数组。
   */
  explicit BorderInfo(float line_width, LineCapMode line_cap, foxit::RGB color, float h_radius, float v_radius, float dash_offset, foxit::FloatArray dash_pattern) :
    line_width(line_width),
    line_cap(line_cap),
    color(color),
    h_radius(h_radius),
    v_radius(v_radius),
    dash_offset(dash_offset) {
    this->dash_pattern.Copy(dash_pattern);
  }

  /**
   * @brief 构造函数，通过另一个边框信息对象。
   *
   * @param[in] other  另一个边框信息对象。
   */
  BorderInfo(const BorderInfo& other) {
    this->line_width = other.line_width;
    this->line_cap = other.line_cap;
    this->color = other.color;
    this->h_radius = other.h_radius;
    this->v_radius = other.v_radius;
    this->dash_offset = other.dash_offset;
    this->dash_pattern.Copy(other.dash_pattern);
  }

  /**
   * @brief 赋值操作符。
   *
   * @param[in] other  另一个边框信息对象，其值将被赋给当前对象。
   *
   * @return 对当前对象自身的引用。
   */
  BorderInfo& operator = (const BorderInfo& other) {
    this->line_width = other.line_width;
    this->line_cap = other.line_cap;
    this->color = other.color;
    this->h_radius = other.h_radius;
    this->v_radius = other.v_radius;
    this->dash_offset = other.dash_offset;
    this->dash_pattern.Copy(other.dash_pattern);
    return *this;
  }

  /**
   * @brief 设置值。
   *
   * @param[in] line_width        边框宽度，以点为单位。这应该是一个非负值。
   * @param[in] line_cap          线端点样式。请参考从 @link foxit::ofd::graphics::BorderInfo::e_LineCapButt @endlink 开始的值，
   *                              应该是这些值中的一个。
   * @param[in] color             边框颜色。
   * @param[in] h_radius          横向圆角半径。
   * @param[in] v_radius          纵向圆角半径。
   * @param[in] dash_offset       虚线偏移量。
   * @param[in] dash_pattern      虚线模式数组。
   *
   * @return 无。
   */
  void Set(float line_width, LineCapMode line_cap, foxit::RGB color, float h_radius, float v_radius, float dash_offset, foxit::FloatArray dash_pattern) {
    this->line_width = line_width;
    this->line_cap = line_cap;
    this->color = color;
    this->h_radius = h_radius;
    this->v_radius = v_radius;
    this->dash_offset = dash_offset;
    this->dash_pattern.Copy(dash_pattern);
  }

  /**
   * @brief 边框宽度，以点为单位。这应该是一个非负值。
   */
  float line_width;

  /**
   * @brief 线端点样式。请参考从 @link foxit::ofd::graphics::BorderInfo::e_LineCapButt @endlink 开始的值，
   *                    应该是这些值中的一个。
   */
  LineCapMode line_cap;

  /**
   * @brief  边框颜色。
   */
  foxit::RGB color;

  /**
   * @brief 横向圆角半径。
   */
  float h_radius;

  /**
   * @brief 纵向圆角半径。
   */
  float v_radius;

  /**
   * @brief 虚线偏移量。
   */
  float dash_offset;

  /**
   * @brief 虚线模式数组。
   */
  foxit::FloatArray dash_pattern;
};

/** 此类表示和OFD图元对象相关的方法。*/
class OFDGraphicsObject : public Base {
 public:
  /**
    * @brief OFD图元对象类型定义枚举类型.
    *
    * @details 该枚举值应单独使用.
    */
  typedef enum _ObjectType {
    /** @brief 对象类型：未知 */
    e_ObjectTypeUnknown   =  0,
    /** @brief 对象类型：页面块。 */
    e_ObjectTypePageBlock  =  2,
    /** @brief 对象类型：组合。 */
    e_ObjectTypeComposite  =  3,
    /** @brief 对象类型：矢量图形。 */
    e_ObjectTypeSVG  =  4,
    /** @brief 对象类型：文字。 */
    e_ObjectTypeText  =  5,
    /** @brief 对象类型：路径。 */
    e_ObjectTypePath  =  6,
    /** @brief 对象类型：图像。 */
    e_ObjectTypeImage   =  7,
    /** @brief 对象类型：视频。 */
    e_ObjectTypeVideo  =  8
  } ObjectType;
  
  /**
   * @brief OFD线端点样式枚举。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _LineCapMode {
    /**
     * @brief 平头端盖。描边在路径的端点处被切断。路径末端之外没有投影。
     */
    e_LineCapButt = 0,
    /**
     * @brief 圆头端盖。在端点周围绘制一个直径等于线宽的半圆弧并填充。
     */
    e_LineCapRound = 1,
    /**
     * @brief 投影方形端盖。描边在路径端点之外继续延伸等于线宽一半的距离，并被切断。
     */
    e_LineCapSquare = 2
  } LineCapMode;
  
  /**
   * @brief OFD线条连接样式枚举。
   *
   * @details 该枚举值应单独使用。
   */
  typedef enum _LineJoinMode {
    /**
     * @brief 斜接线条连接类型。
     *
     * @details 两段描边的外边缘延伸直到它们以一定角度相交。
     */
    e_LineJoinMiter = 0,
    /**
     * @brief 圆角线条连接类型。
     *
     * @details 在两段相交的点周围绘制一个直径等于线宽的圆弧，
     *          连接两段描边的外边缘。
     */
    e_LineJoinRound = 1,
    /**
     * @brief 斜角线条连接类型。
     *
     * @details 两段使用平头端盖完成，并且段末端之外的结果凹口
     *         用三角形填充。
     */
    e_LineJoinBevel = 2
  } LineJoinMode;
  

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

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

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

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

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

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

  /**
   * @brief 获取图元对象资源ID。
   *
   * @return 图元对象资源ID值。
   */
  foxit::uint32 GetID();

  /**
   * @brief 获取图元对象类型。
   *
   * @return 图元对象类型。请参考从 @link foxit::ofd::graphics::OFDGraphicsObject::e_ObjectTypeUnknown @endlink 开始的值，
   *         应该是这些值中的一个。
   */
  ObjectType GetType();

  /**
   * @brief 获取图元对象所在页面的索引号。
   *
   * @return 图元对象所在页面的索引号（由0开始编号）。
   */
  int GetPageIndex();

  /**
   * @brief 获取图元对象名称。
   *
   * @return 图元对象名称值。
   */
  String GetName();

  /**
   * @brief 获取图元对象可见性属性。
   *
   * @return <b>true</b>表示可见，<b>false</b>表示不可见。
   */
  bool IsVisible();

  /**
   * @brief 判断图元对象是否有边框。
   *
   * @return <b>true</b>表示有边框，<b>false</b>表示无边框。
   */
  bool HasBorder();

  /**
   * @brief 获取图元对象边框信息(只有Image和Video对象可能会存在边框)。
   *
   * @return 图元对象边框信息值。
   */
  BorderInfo GetBorderInfo();

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

  /**
   * @brief 获取图元对象矩阵。
   *
   * @return 矩阵值。
   */
  foxit::Matrix GetMatrix();

  /**
   * @brief 获取图元对象alpha属性。
   *
   * @return alpha值（0-255）。
   */
  foxit::uint8 GetAlpha();

  /**
   * @brief 获取图元对象填充颜色。
   *
   * @return 颜色值。
   */
  foxit::RGB GetFillColor();

  /**
   * @brief 获取图元对象勾边颜色。
   *
   * @return 颜色值。
   */
  foxit::RGB GetStrokeColor();

  /**
   * @brief 获取图元对象线宽。
   *
   * @return 线宽值（单位毫米）。
   */
  float GetLineWidth();

  /**
   * @brief 获取图元对象线帽样式。
   *
   * @return 线帽样式值。请参考从 @link foxit::ofd::graphics::OFDGraphicsObject::e_LineCapButt @endlink 开始的值，
   *         应该是这些值中的一个。
   */
  LineCapMode GetLineCap();

  /**
   * @brief 获取线条连接样式。
   *
   * @return 线条连接样式值。请参考从 @link foxit::ofd::graphics::OFDGraphicsObject::e_LineJoinMiter @endlink 开始的值，
   *         应该是这些值中的一个。
   */
  LineJoinMode GetLineJoin();

  /**
   * @brief 获取图元对象斜切限制值。
   *
   * @return 斜切限制值。
   */
  float GetMiterLimit();

  /**
   * @brief 获取图元对象虚线重复样式。
   *
   * @return 图元对象虚线重复样式值。
   */
  float GetDashOffset();

  /**
   * @brief 获取图元对象虚线重复样式数组。
   *
   * @return 图元对象虚线重复样式数组值。
   */
  foxit::FloatArray GetDashPattern();

  /**
   * @brief 设置图元对象名称。
   *
   * @param[in] name          图元对象名称值。
   *
   * @return 无。
   */
  void SetName(const String& name);
  /**
   * @brief 设置图元对象可见性属性。
   *
   * @param[in] visible       是否可见（true可见，false不可见）。
   *
   * @return 无。
   */
  void SetVisible(bool visible);

  /**
   * @brief 设置图元对象边框信息。
   *
   * @param[in] border_info      图元对象边框信息值。
   *
   * @return 无。
   */
  void SetBorderInfo(const BorderInfo& border_info);

  /**
   * @brief 设置图元对象矩形外接框。
   *
   * @param[in] boundary      矩形外接框值。
   *
   * @return 无。
   */
  void SetBoundary(const RectF& boundary);

  /**
   * @brief 设置图元对象矩阵。
   *
   * @param[in] mt            矩阵。
   *
   * @return 无。
   */
  void SetMatrix(const Matrix& mt);

  /**
   * @brief 设置图元对象alpha属性。
   *
   * @param[in] alpha         alpha值（0-255）。
   *
   * @return 无。
   */
  void SetAlpha(foxit::uint8 alpha);

  /**
   * @brief 设置图元对象填充颜色。
   *
   * @param[in] fill_color    颜色值。
   *
   * @return 无。
   */
  void SetFillColor(foxit::uint32 fill_color);

  /**
   * @brief 设置图元对象勾边颜色。
   *
   * @param[in] stroke_color  颜色值。
   *
   * @return 无。
   */
  void SetStrokeColor(foxit::uint32 stroke_color);

  /**
   * @brief 设置图元对象线宽。
   *
   * @param[in] line_width        线宽值（单位毫米）。
   *
   * @return 无。
   */
  void SetLineWidth(float line_width);

  /**
   * @brief 设置图元对象线帽样式。
   *
   * @param[in] line_cap 线帽样式值（默认为e_LineCapButt）。请参考从 @link foxit::ofd::graphics::OFDGraphicsObject::e_LineCapButt @endlink 开始的值，
   *                     应该是这些值中的一个。
   *
   * @return 无。
   */
  void SetLineCap(LineCapMode line_cap = e_LineCapButt);

  /**
   * @brief 设置线条连接样式。
   *
   * @param[in] line_join    样式值。（默认为e_LineJoinMiter）。请参考从 @link foxit::ofd::graphics::OFDGraphicsObject::e_LineJoinMiter @endlink 开始的值，
   *                         应该是这些值中的一个。
   *
   * @return 无。
   */
   void SetLineJoin(LineJoinMode line_join = e_LineJoinMiter);

  /**
   * @brief 设置图元对象斜切限制值。
   *
   * @param[in] miter_limit    斜切限制值。
   *
   * @return 无。
   */
   void SetMiterLimit(float miter_limit);

  /**
   * @brief 设置图元对象虚线重复样式起始值。
   *
   * @param[in] dash_offset    图元对象虚线重复起始值。
   *
   * @return 无。
   */
   void SetDashOffset(float dash_offset);

   /**
    * @brief 设置图元对象虚线重复样式。
    *
    * @param[in] dash_offset          图元对象虚线重复起始值。
    * @param[in] dash_offset_array    重复样式点数据数组，数组大小为2，其中第一个元素表示虚线长度，第二个元素表示虚线间隔的长度。
    *
    * @return 无。
    */
   void SetDashPattern(float dash_offset, const foxit::FloatArray& dash_offset_array);

   /**
    * @brief 创建图元对象动作集合对象。
    *
    * @return 返回图元对象动作集合对象。
    */
   Actions CreateActions();

   /**
    * @brief 获取图元对象的动作集合。
    *
    * @return 返回动作数组对象集合对象。
    */
   Actions GetActions();

   explicit OFDGraphicsObject(FS_HANDLE handle);
};

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

#endif  // FS_OFD_OBJECT_H_
