#ifndef __HUI_INTERNAL_H__
#define __HUI_INTERNAL_H__

#include <linux/mutex.h>
#include <linux/timer.h>
#include <linux/version.h>

#define AVM_LED_INTERNAL
#include <avm/hui/events.h>
#include <avm/hui/led.h>

#include "leds.h"

/* Macro parameters changed in Linux version 4.15 commit 1d27e3e2252ba9d949ca82fbdb73cde102cb2067 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
#define HUI_DEFINE_TIMER(_name, _function) DEFINE_TIMER(_name, _function, 0, 0)
#define HUI_INIT_TIMER(_timer) init_timer(_timer)
typedef unsigned long timer_callback;
#else
#define HUI_DEFINE_TIMER(_name, _function) DEFINE_TIMER(_name, _function)
#define HUI_INIT_TIMER(_timer) timer_setup(_timer, NULL, 0)
typedef struct timer_list *timer_callback;
#endif

int hui_sysfs_init(void);
void hui_sysfs_exit(void);
void events_init(void);
void events_update(void);
void events_exit(void);
int leds_init(void);
void leds_update(void);
void leds_update_output(void);
void leds_exit(void);
int button_init(void);
void button_exit(void);
int generic_gpio_init(void);
void generic_gpio_exit(void);

int device_init(void);

extern struct mutex hui_update_mutex;

/*!
 * This function will schedule a hui update cycle.
 *
 * This should be called when events are delivered or global parameters are
 * change.
 */
extern void hui_schedule_update(void);

/*!
 * Send a button event.
 *
 * This function takes the button id and pressed time and sends the
 * corresponding avm_event containing these values.
 *
 * The special value 0 for pressed_time means that the button has just
 * been pressed down, and a final event with the non-null pressed_time
 * will be send later.
 *
 * @param button_id Button id
 * @param pressed_time 0 for down otherwise denotes press duration
 * @returns 0 or -ENOMEM
 */
extern int avm_hui_send_button_event(unsigned int button_id,
				     unsigned int pressed_time);

extern void *event_source;

struct hui {
	struct colored_kobject obj;

	// 0-100%
	u8 brightness;
	u8 ambient_light;
};

extern struct hui *hui_kobj;

/*
 * On some (older) platforms the firmware is flashed from within the kernel.
 *
 * However the kernel is barley functional at this point, so we need to side
 * step most of the code.
 *
 * One good thing: The flash code only wants to turn the update led on/off.
 */
#if IS_ENABLED(CONFIG_AVM_FLASH_UPDATE)
extern int hui_bare_handle_event(enum _led_event event, int val);
#else
static inline int hui_bare_handle_event(enum _led_event event, int val)
{
	return 0;
}
#endif

const char *hui_button_event_to_name(int id);

#endif