#ifndef _EFL_VIEW_MODEL_EO_H_
#define _EFL_VIEW_MODEL_EO_H_

#ifndef _EFL_VIEW_MODEL_EO_CLASS_TYPE
#define _EFL_VIEW_MODEL_EO_CLASS_TYPE

typedef Eo Efl_View_Model;

#endif

#ifndef _EFL_VIEW_MODEL_EO_TYPES
#define _EFL_VIEW_MODEL_EO_TYPES

#ifdef EFL_BETA_API_SUPPORT
/** Function called when a property is get.
 *
 * @ingroup EflViewModelPropertyGet
 */
typedef Eina_Value * (*EflViewModelPropertyGet)(void *data, const Efl_View_Model *view_model, Eina_Stringshare *property);
#endif /* EFL_BETA_API_SUPPORT */

#ifdef EFL_BETA_API_SUPPORT
/** Function called when a property is set.
 *
 * @ingroup EflViewModelPropertySet
 */
typedef Eina_Future * (*EflViewModelPropertySet)(void *data, Efl_View_Model *view_model, Eina_Stringshare *property, Eina_Value *value);
#endif /* EFL_BETA_API_SUPPORT */


#endif
#ifdef EFL_BETA_API_SUPPORT
/**
 * @brief Efl model providing helpers for custom properties used when linking a
 * model to a view and you need to generate/adapt values for display.
 *
 * There is two ways to use this class, you can either inherit from it and have
 * a custom constructor for example. Or you can just instantiate it and
 * manually define your property on it via callbacks.
 *
 * @ingroup Efl_View_Model
 */
#define EFL_VIEW_MODEL_CLASS efl_view_model_class_get()

EWAPI const Efl_Class *efl_view_model_class_get(void);

/**
 * @brief Add callbacks that will be triggered when someone ask for the
 * specified property name when getting or setting a property.
 *
 * A get or set should at least be provided for this call to succeed.
 *
 * See @ref efl_view_model_property_logic_del
 *
 * @param[in] obj The object.
 * @param[in] property The property to bind on to.
 * @param[in] get Define the get callback called when the
 * @ref efl_model_property_get is called with the above property name.
 * @param[in] set Define the set callback called when the
 * @ref efl_model_property_set is called with the above property name.
 * @param[in] binded Iterator of property name to bind with this defined
 * property see @ref efl_view_model_property_bind.
 *
 * @ingroup Efl_View_Model
 */
EOAPI Eina_Error efl_view_model_property_logic_add(Eo *obj, const char *property, void *get_data, EflViewModelPropertyGet get, Eina_Free_Cb get_free_cb, void *set_data, EflViewModelPropertySet set, Eina_Free_Cb set_free_cb, Eina_Iterator *binded);

/**
 * @brief Delete previously added callbacks that were triggered when someone
 * asked for the specified property name when getting or setting a property.
 *
 * A get or set should at least be provided for this call to succeed.
 *
 * See @ref efl_view_model_property_logic_add
 *
 * @param[in] obj The object.
 * @param[in] property The property to bind on to.
 *
 * @ingroup Efl_View_Model
 */
EOAPI Eina_Error efl_view_model_property_logic_del(Eo *obj, const char *property);

/**
 * @brief Automatically update the field for the event
 * @[Efl.Model.properties,changed] to include property that are impacted with
 * change in a property from the composited model.
 *
 * The source doesn't have to be provided at this point by the composited
 * model.
 *
 * @param[in] obj The object.
 * @param[in] source Property name in the composited model.
 * @param[in] destination Property name in the @ref Efl_View_Model
 *
 * @ingroup Efl_View_Model
 */
EOAPI void efl_view_model_property_bind(Eo *obj, const char *source, const char *destination);

/**
 * @brief Stop automatically updating the field for the event
 * @[Efl.Model.properties,changed] to include property that are impacted with
 * change in a property from the composited model.
 *
 * @param[in] obj The object.
 * @param[in] source Property name in the composited model.
 * @param[in] destination Property name in the @ref Efl_View_Model
 *
 * @ingroup Efl_View_Model
 */
EOAPI void efl_view_model_property_unbind(Eo *obj, const char *source, const char *destination);

/**
 * @brief Define if we will intercept all childrens object reference and bind
 * them through the ViewModel with the same property logic as this one. Be
 * careful of recursivity.
 *
 * This can only be applied at construction time.
 *
 * Set the state of the automatic binding of children object.
 *
 * @param[in] obj The object.
 * @param[in] enable Do you automatically bind children. Default to true.
 *
 * @ingroup Efl_View_Model
 */
EOAPI void efl_view_model_children_bind_set(Eo *obj, Eina_Bool enable);

/**
 * @brief Define if we will intercept all childrens object reference and bind
 * them through the ViewModel with the same property logic as this one. Be
 * careful of recursivity.
 *
 * This can only be applied at construction time.
 *
 * Get the state of the automatic binding of children object.
 *
 * @param[in] obj The object.
 *
 * @return Do you automatically bind children. Default to true.
 *
 * @ingroup Efl_View_Model
 */
EOAPI Eina_Bool efl_view_model_children_bind_get(const Eo *obj);
#endif /* EFL_BETA_API_SUPPORT */

#endif
