#ifndef _EFL_TEXT_CURSOR_EO_H_
#define _EFL_TEXT_CURSOR_EO_H_

#ifndef _EFL_TEXT_CURSOR_EO_CLASS_TYPE
#define _EFL_TEXT_CURSOR_EO_CLASS_TYPE

typedef Eo Efl_Text_Cursor;

#endif

#ifndef _EFL_TEXT_CURSOR_EO_TYPES
#define _EFL_TEXT_CURSOR_EO_TYPES

#ifdef EFL_BETA_API_SUPPORT
/** All available cursor states
 *
 * @ingroup Efl
 */
typedef enum
{
  EFL_TEXT_CURSOR_GET_TYPE_DEFAULT = 0, /**< Main cursor state (alias to "main")
                                         */
  EFL_TEXT_CURSOR_GET_TYPE_MAIN, /**< Main cursor state */
  EFL_TEXT_CURSOR_GET_TYPE_SELECTION_BEGIN, /**< Selection begin cursor state */
  EFL_TEXT_CURSOR_GET_TYPE_SELECTION_END, /**< Selection end cursor state */
  EFL_TEXT_CURSOR_GET_TYPE_PREEDIT_START, /**< Pre-edit start cursor state */
  EFL_TEXT_CURSOR_GET_TYPE_PREEDIT_END, /**< Pre-edit end cursor state */
  EFL_TEXT_CURSOR_GET_TYPE_USER, /**< User cursor state */
  EFL_TEXT_CURSOR_GET_TYPE_USER_EXTRA /**< User extra cursor state */
} Efl_Text_Cursor_Get_Type;
#endif /* EFL_BETA_API_SUPPORT */

#ifdef EFL_BETA_API_SUPPORT
/** Text cursor types
 *
 * @ingroup Efl
 */
typedef enum
{
  EFL_TEXT_CURSOR_TYPE_BEFORE = 0, /**< Cursor type before */
  EFL_TEXT_CURSOR_TYPE_UNDER /**< Cursor type under */
} Efl_Text_Cursor_Type;
#endif /* EFL_BETA_API_SUPPORT */


#endif
#ifdef EFL_BETA_API_SUPPORT
/** Cursor API
 *
 * @ingroup Efl_Text_Cursor
 */
#define EFL_TEXT_CURSOR_INTERFACE efl_text_cursor_interface_get()

EWAPI const Efl_Class *efl_text_cursor_interface_get(void);

/**
 * @brief The object's main cursor.
 *
 * @param[in] obj The object.
 * @param[in] get_type Cursor type
 *
 * @return Text cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI Efl_Text_Cursor_Cursor *efl_text_cursor_get(const Eo *obj, Efl_Text_Cursor_Get_Type get_type);

/**
 * @brief Cursor position
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 * @param[in] position Cursor position
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_position_set(Eo *obj, Efl_Text_Cursor_Cursor *cur, int position);

/**
 * @brief Cursor position
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @return Cursor position
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI int efl_text_cursor_position_get(const Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief The content of the cursor (the character under the cursor)
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @return The unicode codepoint of the character
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI Eina_Unicode efl_text_cursor_content_get(const Eo *obj, const Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Returns the geometry of two cursors ("split cursor"), if logical
 * cursor is between LTR/RTL text, also considering paragraph direction. Upper
 * cursor is shown for the text of the same direction as paragraph, lower
 * cursor - for opposite.
 *
 * Split cursor geometry is valid only  in '|' cursor mode. In this case
 * @c true is returned and @c cx2, @c cy2, @c cw2, @c ch2 are set.
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 * @param[in] ctype The type of the cursor.
 * @param[out] cx The x of the cursor (or upper cursor)
 * @param[out] cy The y of the cursor (or upper cursor)
 * @param[out] cw The width of the cursor (or upper cursor)
 * @param[out] ch The height of the cursor (or upper cursor)
 * @param[out] cx2 The x of the lower cursor
 * @param[out] cy2 The y of the lower cursor
 * @param[out] cw2 The width of the lower cursor
 * @param[out] ch2 The height of the lower cursor
 *
 * @return @c true if split cursor, @c false otherwise.
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI Eina_Bool efl_text_cursor_geometry_get(const Eo *obj, const Efl_Text_Cursor_Cursor *cur, Efl_Text_Cursor_Type ctype, int *cx, int *cy, int *cw, int *ch, int *cx2, int *cy2, int *cw2, int *ch2);

/**
 * @brief Create new cursor
 *
 * @param[in] obj The object.
 *
 * @return Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI Efl_Text_Cursor_Cursor *efl_text_cursor_new(Eo *obj);

/**
 * @brief Free existing cursor
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_free(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Check if two cursors are equal
 *
 * @param[in] obj The object.
 * @param[in] cur1 Cursor 1 object
 * @param[in] cur2 Cursor 2 object
 *
 * @return @c true if cursors are equal, @c false otherwise
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI Eina_Bool efl_text_cursor_equal(Eo *obj, const Efl_Text_Cursor_Cursor *cur1, const Efl_Text_Cursor_Cursor *cur2);

/**
 * @brief Compare two cursors
 *
 * @param[in] obj The object.
 * @param[in] cur1 Cursor 1 object
 * @param[in] cur2 Cursor 2 object
 *
 * @return Difference between cursors
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI int efl_text_cursor_compare(Eo *obj, const Efl_Text_Cursor_Cursor *cur1, const Efl_Text_Cursor_Cursor *cur2);

/**
 * @brief Copy existing cursor
 *
 * @param[in] obj The object.
 * @param[in] dst Destination cursor
 * @param[in] src Source cursor
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_copy(Eo *obj, Efl_Text_Cursor_Cursor *dst, const Efl_Text_Cursor_Cursor *src);

/**
 * @brief Advances to the next character
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_char_next(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advances to the previous character
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_char_prev(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advances to the next grapheme cluster
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_cluster_next(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advances to the previous grapheme cluster
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_cluster_prev(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advances to the first character in this paragraph
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_paragraph_char_first(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advances to the last character in this paragraph
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_paragraph_char_last(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advance to current word start
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_word_start(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advance to current word end
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_word_end(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advance to current line first character
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_line_char_first(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advance to current line last character
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_line_char_last(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advance to current paragraph first character
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_paragraph_first(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advance to current paragraph last character
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_paragraph_last(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advances to the start of the next text node
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_paragraph_next(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Advances to the end of the previous text node
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_paragraph_prev(Eo *obj, Efl_Text_Cursor_Cursor *cur);

/**
 * @brief Jump the cursor by the given number of lines
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 * @param[in] by Number of lines
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_line_jump_by(Eo *obj, Efl_Text_Cursor_Cursor *cur, int by);

/**
 * @brief Set cursor coordinates
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 * @param[in] x X coord to set by.
 * @param[in] y Y coord to set by.
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_coord_set(Eo *obj, Efl_Text_Cursor_Cursor *cur, int x, int y);

/**
 * @brief Set cursor coordinates according to grapheme clusters. It does not
 * allow to put a cursor to the middle of a grapheme cluster.
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 * @param[in] x X coord to set by.
 * @param[in] y Y coord to set by.
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_cluster_coord_set(Eo *obj, Efl_Text_Cursor_Cursor *cur, int x, int y);

/**
 * @brief Adds text to the current cursor position and set the cursor to
 * *after* the start of the text just added.
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 * @param[in] text Text to append (UTF-8 format).
 *
 * @return Length of the appended text.
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI int efl_text_cursor_text_insert(Eo *obj, Efl_Text_Cursor_Cursor *cur, const char *text);

/**
 * @brief Deletes a single character from position pointed by given cursor.
 *
 * @param[in] obj The object.
 * @param[in] cur Cursor object
 *
 * @ingroup Efl_Text_Cursor
 */
EOAPI void efl_text_cursor_char_delete(Eo *obj, Efl_Text_Cursor_Cursor *cur);
#endif /* EFL_BETA_API_SUPPORT */

#endif
