#include <linux/module.h>

#ifndef __AVM_HUI_BUTTON_INTERNAL_H__
#define __AVM_HUI_BUTTON_INTERNAL_H__

enum button_event {
	// Nothing happened, just ignore
	button_event_none,
	// Button has been pressed down
	button_event_down,
	// Button has been released
	button_event_up,
	// Button has been cancelled
	button_event_cancelled,
};

/*!
 * Button actions ignore locks
 *
 * Actions with the IGNORE_LOCK flag set, will be triggered even
 * if the button lock is enabled.
 */
#define BUTTON_FLAG_IGNORE_LOCK BIT(1)

/*!
 * Button requires annother button to be pressed at the same time
 *
 * When this flag is set, another button must be in the same state.
 * That means another button must have the exact same button action
 * (same msg, flags, handle, up, down). When both buttons are pressed
 * and this action is encountered all other buttons are looked at, to
 * see if they are currently in the same state.
 */
#define BUTTON_FLAG_MULTI BIT(2)

struct button;
struct button_action;

typedef void (*button_action_handler)(struct button *button,
				      const struct button_action *,
				      enum button_event event,
				      unsigned long elapsed);

/*!
 * Description what happens when a button is pressed/released
 */
struct button_action {
	/*
	 * Absolute time from button pressed.
	 *
	 * A value of zero is invalid.
	 */
	int ms;
	/* Flags influencing the default handling */
	int flags;

	/* Generic handling, if NULL, default handling will be used */
	button_action_handler handler;

	// Default handling
	int down; // Event to send on down
	int up; // Event to send on up
};

struct button_def {
	const char *name;
	struct button_action *actions;
};

struct button {
	struct kobject kobj;

	const struct button_action *actions;

	/* Index or -1 for no action */
	int current_action;
	/* a time or MAX_JIFFY_OFFSET denoting the button is not pressed */
	unsigned long jiffies_down;
};
#define to_button_obj(obj) container_of(obj, struct button, kobj)

extern struct kobj_type button_ktype;

static inline const char *button_name(const struct button *button)
{
	return kobject_name(&button->kobj);
}

#endif