#ifndef FS_OFD_OFFICENODE_H_
#define FS_OFD_OFFICENODE_H_

#include "common/fs_common.h"

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

/** 此类表示和OFD公文语义相关的操作。*/
class OfficeNode FS_FINAL : public Base {
 public:
  /** @brief 析构函数。 */
  ~OfficeNode();

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

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

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

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

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

  /**
   * @brief 获取标签名称。
   *
   * @return 标签名称。
   */
  String GetTagName();

  /**
   * @brief 获取文本内容。
   *
   * @return 文本内容。
   */
  String GetText();

  /**
   * @brief 判断当前节点是否为组节点。
   *
   * @return <b>true</b> 表示当前节点为组节点，<b>false</b> 表示当前节点不是组节点。
   */
  bool IsGroup();

  /**
   * @brief 获取公文语义子节点数量。
   *
   * @return 子节点数量。
   */
  int GetOfficeNodeCount();

  /**
   * @brief 获取指定索引的公文语义子节点。
   *
   * @param[in] index 指定子节点的索引。有效范围：从0到(<i>count</i>-1)。
   *                  <i>count</i> 由函数 @link foxit::ofd::OfficeNode::GetOfficeNodeCount @endlink 返回。
   *
   * @return 公文语义子节点。
   */
  OfficeNode GetOfficeNode(int index);

  /**
   * @brief 新建一个公文语义子节点，并添加到当前节点下。
   *
   * @param[in] tag_name  子节点标签名称。
   * @param[in] group     是否为组节点。<b>true</b>表示是组节点，<b>false</b>表示不是组节点。
   *
   * @return 新建的公文语义子节点。
   */
  OfficeNode AddOfficeNode(const String& tag_name, bool group);

  /**
   * @brief 删除指定索引的公文语义子节点。
   *
   * @param[in] index 指定子节点的索引。有效范围：从0到(<i>count</i>-1)。
   *                  <i>count</i> 由函数 @link foxit::ofd::OfficeNode::GetOfficeNodeCount @endlink 返回。
   *
   * @return 无。
   */
  void RemoveOfficeNode(int index);

  /**
   * @brief 获取图元对象数量。
   *
   * @return 图元对象数量。
   */
  int GetGraphicsObjectCount();

  /**
   * @brief 获取指定索引的图元对象。
   *
   * @param[in] index 指定图元对象的索引。有效范围：从0到(<i>count</i>-1)。
   *                  <i>count</i> 由函数 @link foxit::ofd::OfficeNode::GetGraphicsObjectCount @endlink 返回。
   *
   * @return 图元对象。
   */
  graphics::OFDGraphicsObject GetGraphicsObject(int index);

  /**
   * @brief 添加图元对象。
   *
   * @param[in] page 指定添加图元对象的页面对象。
   * @param[in] rect 图元对象的位置和大小。
   *
   * @return 无。
   */
  void AddGraphicsObject(const OFDPage& page, foxit::RectF rect);

  /**
   * @brief 添加图元对象。
   *
   * @param[in] page_id 指定添加图元对象的页面ID。
   * @param[in] obj_id  指定添加图元对象的图元对象ID。
   *
   * @return 无。
   */
  void AddGraphicsObject(foxit::uint32 page_id, foxit::uint32 obj_id);

  /**
   * @brief 删除图元对象。
   *
   * @param[in] page_id 指定删除图元对象的页面ID。
   * @param[in] obj_id  指定删除图元对象的图元对象ID。
   *
   * @return 无。
   */
  void RemoveGraphicsObject(foxit::uint32 page_id, foxit::uint32 obj_id);

  /**
   * @brief 设置标签名称。
   *
   * @param[in] name 标签名称。
   *
   * @return 无。
   */
  void SetTagName(const String& name);

  /**
   * @brief 设置权限。
   *
   * @param[in] visible         是否可见。
   * @param[in] printable       是否可打印。
   * @param[in] extractable     是否可提取。
   * @param[in] replace         替换文本内容。
   * @param[in] control_sub     是否控制子节点权限。
   *
   * @return 无。
   */
  void SetPermission(bool visible, bool printable, bool extractable, const String& replace, bool control_sub);

  /**
   * @brief 设置属性值。
   *
   * @param[in] key       属性关键字。
   * @param[in] value     属性值。
   *
   * @return 无。
   */
  void SetAttributeValue(const String& key, const String& value);

  /**
   * @brief 设置公文语义节点的Schema信息。
   *
   * @param[in] schema        Schema值。
   * @param[in] name_space    命名空间值。
   * @param[in] root_name     根节点名称值。
   *
   * @return 无。
   */
  void SetOfficeSchema(const String& schema, const String& name_space, const String& root_name);

  explicit OfficeNode(FS_HANDLE handle);
};

}  // namespace ofd
}  // namespace foxit

#endif  // FS_OFD_OFFICENODE_H_
