#ifndef _EFL_MODEL_BASE_EO_H_
#define _EFL_MODEL_BASE_EO_H_

#ifndef _EFL_MODEL_BASE_EO_CLASS_TYPE
#define _EFL_MODEL_BASE_EO_CLASS_TYPE

typedef Eo Efl_Model_Base;

#endif

#ifndef _EFL_MODEL_BASE_EO_TYPES
#define _EFL_MODEL_BASE_EO_TYPES


#endif
#define EFL_MODEL_BASE_INTERFACE efl_model_base_interface_get()

EAPI const Eo_Class *efl_model_base_interface_get(void) EINA_CONST;

/**
 *
 * Get a load emodel current status.
 *
 * @return: @c Efl_Model_Load_Status
 *
 * By convention this means get the current model status.
 * Possible values are defined Efl_Model_Load_Status enumerator.
 *
 * @see Efl_Model_Load_Status
 * @see efl_model_load
 *
 * @since 1.14
 *
 *
 */
EOAPI Efl_Model_Load_Status  efl_model_load_status_get(void);

/**
 *
 * Get properties from model.
 *
 * @return: @c Efl_Model_Load_Status
 *
 * properties_get is due to provide callers a way the fetch the current
 * properties implemented/used by the model.
 * The event EFL_MODEL_EVENT_PROPERTIES_CHANGE will be raised to notify listeners
 * of any modifications in the properties.
 *
 * @see EFL_MODEL_EVENT_PROPERTIES_CHANGE
 * @since 1.14
 *
 * @param[out] properties array of current properties
 *
 */
EOAPI Efl_Model_Load_Status  efl_model_properties_get(Eina_Array * const*properties);

/**
 *
 * Set a property value of a given property name.
 *
 * @return: @c EINA_TRUE, on success, @c EINA_FALSE in readonly property or error
 *
 * The caller must ensure to call at least efl_model_prop_list before being
 * able to see/set properties.
 * This function sets a new property value into given property name. Once
 * the operation is completed the concrete implementation should raise
 * EFL_MODEL_EVENT_PROPERTIES_CHANGE event in order to notify listeners of the
 * new value of the property.
 *
 * If the model doesn't have the property then there are two possibilities,
 * either raise an error or create the new property in model
 *
 * @see efl_model_property_get
 * @see EFL_MODEL_EVENT_PROPERTIES_CHANGE
 * @since 1.14
 *
 * @param[in] property Property name
 * @param[in] value New value
 *
 */
EOAPI Efl_Model_Load_Status  efl_model_property_set(const char * property, const Eina_Value *value);

/**
 *
 * Retrieve the value of a given property name.
 *
 * @return: @c Load Status, on success, @c EFL_MODEL_LOAD_STATUS_ERROR otherwise
 *
 * property_get will only be available when load status is equal to
 * EFL_MODEL_LOAD_STATUS_LOADED.
 *
 * At this point the caller is free to get values from properties.
 * The event EFL_MODEL_EVENT_PROPERTIES_CHANGE may be raised to notify
 * listeners of the property/value.
 *
 * @see efl_model_properties_get
 * @see EFL_MODEL_EVENT_PROPERTIES_CHANGE
 *
 * @since 1.14
 *
 * @param[in] property Property name
 * @param[out] value New value
 *
 */
EOAPI Efl_Model_Load_Status  efl_model_property_get(const char * property, const Eina_Value **value);

/**
 *
 * Get children slice OR full range.
 *
 * @return: @c Efl_Model_Load_Status. See below for more info.
 *
 * Before being able to get the children list the model status must be
 * on loaded status (EFL_MODEL_LOAD_STATUS_LOADED).
 * However there may be circunstancies where the model could be
 * in a different state, in such cases it is advisable
 * to simply return: its current state, which will be
 * of course, different than @c EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN.
 * When children accessor is return:ed as NULL one should then
 * test the current load status return:ed by @children_slice_get
 * in order to check against an empty list or real error.
 *
 * children_slice_get behaves in two different ways, it may provide
 * the slice if both @c start AND @c count are non-zero OR full range otherwise.
 *
 * The return:ed Eina_Accessor must be freed when it is no longer needed and
 * eo_unref() must be invoked for children if caller wants a copy.
 *
 * Since 'slice' is a range, for example if we have 20 childs a slice could be
 * the range from 3(start) to 4(count), see:
 * child 0  [no]
 * child 1  [no]
 * child 2  [yes]
 * child 3  [yes]
 * child 4  [yes]
 * child 5  [yes]
 * child 6  [no]
 * child 7  [no]
 *
 * Optionally the user can call children_count_get to know
 * the number of children so a valid range can be known in advance.
 *
 * Below are examples of both usage types: slices and full ranges.
 * @code
 *
 * // Returns full list
 * eo_do(obj, efl_model_children_slice_get(0, 0, &children_accessor));
 *
 * // Returns 5 items, counting from item #5
 * eo_do(obj, efl_model_children_slice_get(5, 5, &children_accessor));
 *
 * @endcode
 *
 * @see efl_model_children_get
 * @see efl_model_children_count_get
 * @see efl_model_load
 * @see efl_model_load_status_get
 * @since 1.14
 *
 * @param[in] start Range begin - start from here. If start and count are 0 slice is ignored.
 * @param[in] count Range size. If count and start are 0 slice is ignored.
 * @param[out] children_accessor No description supplied.
 *
 */
EOAPI Efl_Model_Load_Status  efl_model_children_slice_get(unsigned start, unsigned count, Eina_Accessor **children_accessor);

/**
 *
 * Get children count.
 *
 * @return: @c EINA_TRUE, on success, @c EINA_FALSE otherwise
 *
 * When efl_model_load is completed efl_model_coildren_count_get can be use
 * to get the number of children. children_count_get can also be used
 * before calling children_slice_get so a valid range is known.
 * Event EFL_MODEL_CHILDREN_COUNT_CHANGED is emitted when count is finished.
 *
 * @see efl_model_children_get
 * @see efl_model_children_slice_get
 * @see efl_model_load
 * @see efl_model_load_status_get
 * @since 1.14
 *
 * @param[out] children_count No description supplied.
 *
 */
EOAPI Efl_Model_Load_Status  efl_model_children_count_get(unsigned *children_count);

/**
 *
 * Load emodel.
 *
 * By convention this means loading data from an external source and populating
 * the models properties and children with it. For example in the case of file
 * system backed model, this means opening the relevant files and reading the
 * data from them(creating the properties and children from it).
 * the model emit EFL_MODEL_EVENT_LOAD_STATUS after end with Efl_Model_Load_Status
 * @warning This convention should be followed, but no guarantees of behaviour
 * by user defined types can be given.
 *
 * Alternatively is possible to use properties_load to load only properties
 * and children_load to load only children. If efl_model_load is called then
 * calling properties_load and/or children_load is not necessary.
 *
 * @see Efl_Model_Load_Status
 * @see efl_model_properties_load
 * @see efl_model_children_load
 * @see efl_model_unload
 * @see efl_model_load_status_get
 *
 * @since 1.14
 * 
 *
 *
 */
EOAPI void  efl_model_load(void);

/**
 *
 * Unload emodel.
 *
 * By convention this means releasing data received/read from an external source. For
 * example of a database backed model this might mean releasing the iterator for
 * the currently loaded data or deleting a temporary table.
 * the model emit EFL_MODEL_EVENT_LOAD_STATUS after end with model load status
 * @warning This convention should be followed, but no guarantees of behaviour
 * by user defined types can be given.
 *
 * @see Efl_Model_Load_Status
 * @see efl_model_load
 * @see efl_model_load_status_get
 *
 * @since 1.14
 * 
 *
 *
 */
EOAPI void  efl_model_unload(void);

/**
 *
 * Properties emodel load.
 *
 * By convention this means loading data from an external source and populating
 * the models properties only. This method is a subset of efl_model_load, meaning that
 * it won't load children, it is a hint.
 * For loadind both properties and children use efl_model_load
 * instead.
 *
 * @see efl_model_load
 *
 * @since 1.14
 * 
 *
 *
 */
EOAPI void  efl_model_properties_load(void);

/**
 *
 * Children emodel load.
 *
 * By convention this means loading data from an external source and populating
 * the models children only. This method is a subset of efl_model_load, meaning that
 * it won't load properties. For loadind both properties and children use efl_model_load
 * instead.
 *
 * @see efl_model_load
 *
 * @since 1.14
 * 
 *
 *
 */
EOAPI void  efl_model_children_load(void);

/**
 *
 * Add a new child.
 *
 * @return: @c Emodel* on success, @c NULL otherwise
 *
 * Add a new child, possibly dummy, depending on the implementation,
 * of a internal keeping. When the child is effectively
 * added the event EFL_MODEL_EVENT_CHILD_ADD is then raised and the new child
 * is kept along with other children.
 *
 * @see EFL_MODEL_EVENT_CHILD_ADD
 * @see load_status_get
 *
 * @since 1.14
 * 
 *
 *
 */
EOAPI Eo * efl_model_child_add(void);

/**
 *
 * Remove a child.
 *
 * @return: @c Efl_Model_Load_Status on success, @c EFL_MODEL_LOAD_STATUS_ERROR otherwise.
 *
 * Remove a child of a internal keeping. When the child is effectively
 * removed the event EFL_MODEL_EVENT_CHILD_REMOVED is then raised to give a
 * chance for listeners to perform any cleanup and/or update references.
 *
 * @see EFL_MODEL_EVENT_CHILD_REMOVED
 * @since 1.14
 * 
 *
 * @param[in] child Child to be removed
 *
 */
EOAPI Efl_Model_Load_Status  efl_model_child_del(Eo *child);

EOAPI extern const Eo_Event_Description _EFL_MODEL_BASE_EVENT_LOAD_STATUS;
EOAPI extern const Eo_Event_Description _EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED;
EOAPI extern const Eo_Event_Description _EFL_MODEL_BASE_EVENT_CHILD_ADDED;
EOAPI extern const Eo_Event_Description _EFL_MODEL_BASE_EVENT_CHILD_REMOVED;
EOAPI extern const Eo_Event_Description _EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED;

/**
 * Event dispatch when load status changes
 */
#define EFL_MODEL_BASE_EVENT_LOAD_STATUS (&(_EFL_MODEL_BASE_EVENT_LOAD_STATUS))

/**
 * Event dispatched when properties list is available.
 */
#define EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED (&(_EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED))

/**
 * Event dispatched when new child is added.
 */
#define EFL_MODEL_BASE_EVENT_CHILD_ADDED (&(_EFL_MODEL_BASE_EVENT_CHILD_ADDED))

/**
 * Event dispatched when child is removed.
 */
#define EFL_MODEL_BASE_EVENT_CHILD_REMOVED (&(_EFL_MODEL_BASE_EVENT_CHILD_REMOVED))

/**
 * Event dispatched when children count is finished.
 */
#define EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED (&(_EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED))

#endif
