/* ***********************************
 *	Application/Приложение
 */

#ifndef SDK_APPS_H
#define SDK_APPS_H

#include <loader.h>
#include <events.h>

typedef UINT16	REG_ID_T;

#define APP_NAME_LEN			13
#define APP_STATE_NAME_LEN		13
#define STATE_HANDLERS_END		((UINT32)(-1))
#define STATE_HANDLERS_RESERVED	((UINT32)(-2))	// reserved 4 loader



typedef enum
{
	ENTER_STATE_ENTER,
	ENTER_STATE_RESUME
} ENTER_STATE_TYPE_T;

typedef enum
{
	EXIT_STATE_EXIT,
	EXIT_STATE_SUSPEND
} EXIT_STATE_TYPE_T;

typedef UINT16	APP_ID_T;

typedef UINT32	EVENT_HANDLER_T( EVENT_STACK_T * ev_st,  void * app );    // Обработичк события
typedef UINT32	ENTER_STATE_FUNC_T( EVENT_STACK_T * ev_st,  void * app,  ENTER_STATE_TYPE_T type );
typedef UINT32	EXIT_STATE_FUNC_T( EVENT_STACK_T * ev_st,  void * app,  EXIT_STATE_TYPE_T type );


typedef struct
{
	EVENT_CODE_T	code;
	EVENT_HANDLER_T   *hfunc;
} EVENT_HANDLER_ENTRY_T;

typedef struct
{
	UINT8							state;
	ENTER_STATE_FUNC_T *			enter_fn;
	EXIT_STATE_FUNC_T *				exit_fn;
	const EVENT_HANDLER_ENTRY_T	*	htable;
} STATE_HANDLERS_ENTRY_T;

/* Структура приложения */
typedef struct
{
	UINT8					unk1[20];
	UINT32					unk2;
	UINT32					unk3;		// pointer
	UIS_DIALOG_T			dialog;
	UINT32					unk4;
	SU_PORT_T				port;
	void					*unk5;
	EVENT_HANDLER_T			*exit_fn;
	STATE_HANDLERS_ENTRY_T	*handlers_tbl;
	UINT32					unk6; // always 0
	//56
	UINT8					pad1[16];
	//72
	UINT8					token_status;
	UINT8					unk7;
	BOOL					focused;
	UINT8					state;	
		
	UINT8					pad2[4];
} APPLICATION_T; //size = 80

enum {
	APP_TYPE_BG,
	APP_TYPE_FOCUS
};

typedef struct {
	UINT8			state;
	char			name[APP_STATE_NAME_LEN];
} STATE_NAME_ENTRY_T;

enum {
	PRIORITY2_PRIMARY = 0,
	PRIORITY2_SECONDARY
};

#ifdef __cplusplus
extern "C" {
#endif

/* Зарегистрировать Application */
UINT32 APP_Register( const EVENT_CODE_T *			reg_table,
					UINT8							reg_count,
					const STATE_HANDLERS_ENTRY_T *	state_handlers,
					UINT8							state_count,
					void *							start_fn );

/* Искать приложение по reg_id */
UINT32 AFW_InquireRoutingStackByRegId( REG_ID_T reg_id );

APPLICATION_T * APP_InitAppData( void *			main_event_handler,
								size_t			sizeof_app,
								REG_ID_T		reg_id,
								UINT32			sizeof_hist,	// размер структуры, в которой хранится вся инфа для безглючной навигации по стэку истории
								UINT16			history_size,	// глубина стэка истории
								UINT32			priority,
								UINT16			priority2,
								UINT8			type,
								UINT8			param8 );	// =0

APPLICATION_T * APP_InitData( void *	main_event_handler,
							UINT32		sizeof_app,
							REG_ID_T	reg_id,
							UINT32		sizeof_hist,		// =0
							UINT16		history_size,
							UINT32		priority,
							UINT16		priority2 );

/* Стандартная функция управления ивентами для нефоновых приложений */
void APP_HandleEvent( EVENT_STACK_T *		ev_st,
					APPLICATION_T *			app,
					APP_ID_T				app_id,
					REG_ID_T				reg_id );

/* Стандартная функция управления ивентами для фоновых приложений */
void APP_HandleEventPrepost( EVENT_STACK_T *	ev_st,
							void *				app,
							APP_ID_T			app_id,
							REG_ID_T			reg_id );
/* Старт приложения с заданного стэйта */
UINT32 APP_Start( EVENT_STACK_T *				ev_st,
				void *							app,
				UINT8							start_state,
				const STATE_HANDLERS_ENTRY_T *	state_handlers,
				EVENT_HANDLER_T *				exit_fn,
				const char *					app_name,
				STATE_NAME_ENTRY_T *			state_names );
/* Закрытие приложения, освобождение памяти выделенной под структуру приложения */
UINT32 APP_Exit( EVENT_STACK_T *	ev_st,
				void *				app,
				void *				param2 );	// указатель на стэк истории

/* Сменить текущий state
   При этом будет вызвана функция выхода из текущего state и ф-я входа в новый */
UINT32 APP_UtilChangeState( UINT8 new_state,  EVENT_STACK_T * ev_st,  void * app );



UINT32 APP_UtilHistSaveAndChangeState( UINT32 param0, UINT8 new_state, EVENT_STACK_T * ev_st, void * app );

UINT32 APP_UtilHistGoToPrevState( UINT32 param0, UINT8 new_state, EVENT_STACK_T * ev_st, void * app );




				/* Функции таймера - не проверены */

/* Когда таймер срабатывает, он создаёт ивент EV_TIMER_EXPIRED, attachment которого указывает на DL_TIMER_DATA_T */

typedef struct
{
	UINT32		time;
	UINT32		ID;
} DL_TIMER_DATA_T;

/*  Запустить таймер, который сработает через time мс */
UINT32 APP_UtilStartTimer( UINT32 time,  UINT32 ID,  void * app ); // ID будет в DL_TIMER_DATA_T при обработке ивента

/*  Запустить таймер, который будет срабаывать через каждые time мс */
UINT32 APP_UtilStartCyclicalTimer( UINT32 time,  UINT32 ID,  void * app );

/* Остановить таймер */
UINT32 APP_UtilStopTimer( void * app );





// Имя приложения с app_id
UINT32 APP_UtilGetAppName( UINT16 app_id, char * app_name );


#ifdef __cplusplus
} /* extern "C" */
#endif

#endif // SDK_APPS_H