/**
 * @file lv_bar.h
 *
 */

#ifndef LV_BAR_H
#define LV_BAR_H

#ifdef __cplusplus
extern "C" {
#endif

/*********************
 *      INCLUDES
 *********************/
#include "../../lv_conf_internal.h"

#if LV_USE_BAR != 0

#include "../../core/lv_obj.h"
#include "../../misc/lv_anim.h"
#include "../label/lv_label.h"
#include "../../core/lv_observer.h"

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/
typedef enum {
    LV_BAR_MODE_NORMAL,
    LV_BAR_MODE_SYMMETRICAL,
    LV_BAR_MODE_RANGE
} lv_bar_mode_t;

typedef enum {
    LV_BAR_ORIENTATION_AUTO,
    LV_BAR_ORIENTATION_HORIZONTAL,
    LV_BAR_ORIENTATION_VERTICAL
} lv_bar_orientation_t;

LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_bar_class;

#if LV_USE_OBJ_PROPERTY
enum _lv_property_bar_id_t {
    LV_PROPERTY_ID(BAR, VALUE,          LV_PROPERTY_TYPE_INT,   0),
    LV_PROPERTY_ID(BAR, START_VALUE,    LV_PROPERTY_TYPE_INT,   1),
    LV_PROPERTY_ID(BAR, MIN_VALUE,      LV_PROPERTY_TYPE_INT,   2),
    LV_PROPERTY_ID(BAR, MAX_VALUE,      LV_PROPERTY_TYPE_INT,   3),
    LV_PROPERTY_ID(BAR, MODE,           LV_PROPERTY_TYPE_INT,   4),
    LV_PROPERTY_ID(BAR, ORIENTATION,    LV_PROPERTY_TYPE_INT,   5),
    LV_PROPERTY_BAR_END,
};
#endif

/**********************
 * GLOBAL PROTOTYPES
 **********************/

/**
 * Create a bar object
 * @param parent        pointer to an object, it will be the parent of the new bar
 * @return              pointer to the created bar
 */
lv_obj_t * lv_bar_create(lv_obj_t * parent);

/*=====================
 * Setter functions
 *====================*/

/**
 * Set a new value on the bar
 * @param obj           pointer to a bar object
 * @param value         new value
 * @param anim          LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately
 */
void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim);

/**
 * Set a new start value on the bar
 * @param obj             pointer to a bar object
 * @param start_value     new start value
 * @param anim            LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately
 */
void lv_bar_set_start_value(lv_obj_t * obj, int32_t start_value, lv_anim_enable_t anim);

/**
 * Set minimum and the maximum values of a bar
 * @param obj       pointer to the bar object
 * @param min       minimum value
 * @param max       maximum value
 * @note If min is greater than max, the drawing direction becomes to the opposite direction.
 */
void lv_bar_set_range(lv_obj_t * obj, int32_t min, int32_t max);

/**
 * Set minimum value of a bar
 * @param obj       pointer to the bar object
 * @param min       minimum value
 */
void lv_bar_set_min_value(lv_obj_t * obj, int32_t min);

/**
 * Set maximum value of a bar
 * @param obj       pointer to the bar object
 * @param max       maximum value
 */
void lv_bar_set_max_value(lv_obj_t * obj, int32_t max);

/**
 * Set the type of bar.
 * @param obj       pointer to bar object
 * @param mode      bar type from `lv_bar_mode_t`
 */
void lv_bar_set_mode(lv_obj_t * obj, lv_bar_mode_t mode);

/**
 * Set the orientation of bar.
 * @param obj           pointer to bar object
 * @param orientation   bar orientation from `lv_bar_orientation_t`
 */
void lv_bar_set_orientation(lv_obj_t * obj, lv_bar_orientation_t orientation);

/*=====================
 * Getter functions
 *====================*/

/**
 * Get the value of a bar
 * @param obj       pointer to a bar object
 * @return          the value of the bar
 */
int32_t lv_bar_get_value(const lv_obj_t * obj);

/**
 * Get the start value of a bar
 * @param obj       pointer to a bar object
 * @return          the start value of the bar
 */
int32_t lv_bar_get_start_value(const lv_obj_t * obj);

/**
 * Get the minimum value of a bar
 * @param obj       pointer to a bar object
 * @return          the minimum value of the bar
 */
int32_t lv_bar_get_min_value(const lv_obj_t * obj);

/**
 * Get the maximum value of a bar
 * @param obj       pointer to a bar object
 * @return          the maximum value of the bar
 */
int32_t lv_bar_get_max_value(const lv_obj_t * obj);

/**
 * Get the type of bar.
 * @param obj       pointer to bar object
 * @return          bar type from `lv_bar_mode_t`
 */
lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj);

/**
 * Get the orientation of bar.
 * @param obj       pointer to bar object
 * @return          bar orientation from `lv_bar_orientation_t`
 */
lv_bar_orientation_t lv_bar_get_orientation(lv_obj_t * obj);

/**
 * Give the bar is in symmetrical mode or not
 * @param obj       pointer to bar object
 * @return          true: in symmetrical mode false : not in
*/
bool lv_bar_is_symmetrical(lv_obj_t * obj);

#if LV_USE_OBSERVER
/**
 * Bind an integer or float Subject to a Bar's value.
 * @param obj       pointer to Bar
 * @param subject   pointer to Subject
 * @return          pointer to newly-created Observer
 */
lv_observer_t * lv_bar_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif

/**********************
 *      MACROS
 **********************/

#endif /*LV_USE_BAR*/

#ifdef __cplusplus
} /*extern "C"*/
#endif

#endif /*LV_BAR_H*/
