#ifndef _OSWALD_H
#define _OSWALD_H
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define OSWALD_VERSION "v0.3antartica1"

//#define DEBUG 1
#ifdef DEBUG
#define dbg_out( args... ) fprintf(stderr, args)
#else
#define dbg_out( args... ) do {} while (0)
#endif

typedef uint8_t boolean;
#ifdef TRUE
#undef TRUE
#endif
#define TRUE 1
#ifdef FALSE
#undef FALSE
#endif
#define FALSE 0
#ifndef NULL
#define NULL 0
#endif

typedef struct {
	uint8_t	hour;
	uint8_t	minute;
	uint8_t	second;
	uint8_t	day;
	uint8_t	wday; // day in week, 0=sunday, 1=monday,...
	uint8_t	month;
	uint16_t	year;
	boolean	clk24hr;
	boolean day_first;
} clock_state;

#define WDAY_SUNDAY	(1 << 0)
#define WDAY_MONDAY	(1 << 1)
#define WDAY_TUESDAY	(1 << 2)
#define WDAY_WEDNESDAY	(1 << 3)
#define WDAY_THURSDAY	(1 << 4)
#define WDAY_FRIDAY	(1 << 5)
#define WDAY_SATURDAY	(1 << 6)
typedef struct {
	uint8_t	hour;
	uint8_t	minute;
	uint8_t	wday; // bitfield 0 to 6, 1=sunday, 2=monday, 4=tuesday...
} alarm_clk;

typedef enum {
	IDLE_SCREEN = 0,
	MAIN_MENU_SCREEN,
	ALARM_SETUP_SCREEN,
	STOP_WATCH_SCREEN,
	BLUETOOTH_SCREEN,
	ACCEL_DISPLAY_SCREEN,
	MESSAGES_SCREEN,
	INFO_SCREEN,
	LAST_SCREEN,		// a marker for the last (not valid) screen)
	MESSAGE_SCREEN,
	MENU_TEST_SCREEN,
	APPLICATION_SCREEN,
	DATETIME_SETTING_SCREEN,
	ALARM_SCREEN,
	CALENDAR_OVERVIEW_SCREEN,
	SCREENS_END,
} screen_number;

typedef enum {
	BUTTON_A = 0,
	BUTTON_B,
	BUTTON_C,
	BUTTON_D,
	BUTTON_E,
	BUTTON_F,
} watch_button;

#define EVENT_SCREEN_VISIBLE		(1<<0)		// screen just became visible
#define EVENT_SCREEN_DESTROY		(1<<1)		// screen is destroyed
#define EVENT_ONE_SEC_TIMER		(1<<2)		// one second timer for reguler clock
#define EVENT_HALF_SEC_TIMER		(1<<3)		// half second timer for blinking displays
#define EVENT_CS_TIMER			(1<<4)		// centisecond timer, e.g. for stop watch
#define EVENT_USER_BUTTONS		(1<<5)		// button presses
#define EVENT_ACCEL_UPDATE		(1<<6)		// accelerometer updates
#define EVENT_AMBIENTLIGHT_UPDATE	(1<<7)		// ambient light sensor updates
#define EVENT_POWER_CHANGE		(1<<8)		// power source status change
#define EVENT_COMMS			(1<<9)		// communication, like Bluetooth I/O
#define EVENT_POWER_STATE		(1<<10)		// power source changed or similar

typedef enum {
	EVENT_RET_UNHANDLED = 0,
	EVENT_RET_HANDLED,
	EVENT_RET_ERR
} event_ret_t;

typedef struct {
	uint16_t event_mask;				// the event the screen wants to receive
	event_ret_t (*event_func)(uint16_t event, void *data);	// callback for events
	void *user_data;
} watch_screen;

typedef struct {
	screen_number	screen_id;
	watch_screen *screen;		// the current screen
	boolean pending_idle;
} watch_state;

typedef struct {
	int8_t	x;
	int8_t	y;
	int8_t	z;
} accel_data_t;

#define POWER_SOURCE_BATTERY	0
#define POWER_SOURCE_EXTERNAL	1

#define POWER_CHARGER_DONE	0
#define POWER_CHARGER_PRECHARGE	1
#define POWER_CHARGER_CHARGING	2
#define POWER_CHARGER_UNK	3

typedef struct {
	uint8_t	source;
	uint8_t	charge_state;
	uint8_t	percent;
	uint16_t	level;
} power_state;

typedef enum {
	BLUETOOTH_OFF = 0,
	BLUETOOTH_ON,
	BLUETOOTH_CONNECTED,
	BLUETOOTH_ILL
} bluetooth_state;

#endif