/**
 * DreamShell luaKOS
 * Using all functions with prefix - "DS."
 *
 */

#define DS_STATE_RUNNING 0
#define DS_STATE_SLEEP 1
#define DS_STATE_SHUTDOWN 2


int GetState();
void SetState(int state);

char *GetWorkPath();
void SetWorkPath(char *path);

int GetArch();
uint32 GetVersion();
char *GetVersionString();
const char *GetVersionBuildTypeString(int type);


void dbgio_set_dev_ds();
void dbgio_set_dev_scif();
void dbgio_set_dev_fb();
void dbgio_set_dev_sd();


int UnregisterLuaLib(const char *name);


typedef struct Item {

        const char *name;
        uint32 id;
        ListItemType type;
        void *data;
		uint32 size;
   
} Item_t;


typedef enum {
	
	LIST_ITEM_USERDATA = 0,
	LIST_ITEM_SDL_SURFACE,
	LIST_ITEM_SDL_RWOPS,

	LIST_ITEM_GUI_SURFACE,
	LIST_ITEM_GUI_FONT,
	LIST_ITEM_GUI_WIDGET,

	LIST_ITEM_MODULE,
	LIST_ITEM_APP,
	LIST_ITEM_EVENT,
	LIST_ITEM_THREAD,
	LIST_ITEM_CMD,
	LIST_ITEM_LUA_LIB
	
} ListItemType;

Item_list_t *listMake();
void listDestroy(Item_list_t *lst, listFreeItemFunc *ifree);

uint32 listGetLastId(Item_list_t *lst);

Item_t *listAddItem(Item_list_t *lst, ListItemType type, const char *name, void *data, uint32 size);
void listRemoveItem(Item_list_t *lst, Item_t *i, listFreeItemFunc *ifree);

Item_t *listGetItemByName(Item_list_t *lst, const char *name);
Item_t *listGetItemByNameAndType(Item_list_t *lst, const char *name, ListItemType type);
Item_t *listGetItemById(Item_list_t *lst, uint32 id);

Item_t *listGetItemFirst(Item_list_t *lst);
Item_t *listGetItemNext(Item_t *i);



typedef struct Thread {
	
    kthread_t *thd;
    const char *name;
    int id;
    
} Thread_t;


int InitThreads();
void ShutdownThreads();

Thread_t *CreateThreadLua(const char *routine, const char *name);
int DestroyThread(Thread_t *p);
int RemoveThread(Thread_t *p);

int SetThreadPrio(Thread_t *p, int prio);

Thread_t *GetThreadByName(const char *name);
Thread_t *GetThreadById(int id);
Item_list_t *GetThreadList(); 
Thread_t *GetCurrentThread();

Thread_t *VoidToThread(void *ptr);



#define APP_STATE_OPENED 0x00000001
#define APP_STATE_LOADED 0x00000002
#define APP_STATE_READY 0x00000004
#define APP_STATE_PROCESS 0x00000008
#define APP_STATE_SLEEP 0x00000020
#define APP_STATE_WAIT_UNLOAD 0x00000040

typedef struct App {
    
    const char *fn;
    const char *name;
    const char *icon;
    const char *ver;
    int id;
    
    Item_list_t *resources;
    Item_list_t *elements;
    mxml_node_t *xml;
    
    GUI_Widget *body;
    
    Thread_t *thd;
    void *lua;
    
    int state;

} App_t;



int InitApps();
void ShutdownApps();

Item_list_t *GetAppList();
App_t *GetAppById(int id);
App_t *GetAppByFileName(const char *fn);
App_t *GetAppByName(const char *name);
App_t *GetCurApp();

App_t *AddApp(const char *fn);
int RemoveApp(App_t *app);

int OpenApp(App_t *app);
int CloseApp(App_t *app, int unload);
int SwitchApp(App_t *old_app, App_t *new_app, int unload);

void UnLoadOldApps();

int SetAppSleep(App_t *app, int sleep);

int LoadApp(App_t *app, int build);
int UnLoadApp(App_t *app);
void UnloadAppResources(Item_list_t *lst);

int BuildAppBody(App_t *app);
int AddToAppBody(App_t *app, GUI_Widget *widget);
int RemoveFromAppBody(App_t *app, GUI_Widget *widget);

int CallAppBodyEvent(App_t *app, char *event);
void WaitApp(App_t *app);

char *FindXmlAttr(char *name, mxml_node_t *node, char *defValue);
GUI_Surface *getElementSurface(App_t *app, char *name);

App_t *VoidToApp(void *ptr);


#define EVENT_STATE_ACTIVE 0
#define EVENT_STATE_SLEEP 1

#define EVENT_TYPE_INPUT 0
#define EVENT_TYPE_VIDEO 1


typedef struct Event {

    const char *name;
    int id;
	void *event;
	void *param;
    int state;
    int type;
       
} Event_t;


int InitEvents();
void ShutdownEvents();

Event_t *AddEventLua(const char *name, int type, const char *event);
int RemoveEvent(Event_t *e);

int SetEventState(Event_t *e, int state);

Item_list_t *GetEventList();
Event_t *GetEventById(int id);
Event_t *GetEventByName(const char *name);

void PushEvents(SDL_Event *event, int type);
void PushInputEvents(SDL_Event *event);
void PushVideoEvents();
void ProcessEvents(SDL_Event *event);

Event_t *VoidToEvent(void *ptr);



typedef enum {
	CMD_OK = 0,			/* 0 */
	CMD_NO_ARG,         /* 1 */
	CMD_ERROR,		    /* 2 */
	CMD_NOT_EXISTS		/* 3 */
} CMD_RESULT;



typedef enum {
	CMD_TYPE_INTERNAL = 0,	/* 0 */
	CMD_TYPE_ELF,			/* 1 */
	CMD_TYPE_LUA,		    /* 2 */
	CMD_TYPE_DSC,		    /* 3 */
	CMD_TYPE_UKNOWN		/* 4 */
} CMD_TYPES;


typedef struct Cmd {

	const char *command;
	const char *desc;
	void *handler;
	
} Cmd_t;


int CheckExtCmdType(const char *fn);

Cmd_t *AddCmdLua(const char *cmd, const char *helpmsg, const char *handler);
void RemoveCmd(Cmd_t *cmd);

Item_list_t *GetCmdList();
Cmd_t *GetCmdByName(const char *name);

int InitCmd(); 
void ShutdownCmd();


void SetConsoleDebug(int mode);

int dsystem(const char *buff); 
int dsystem_script(const char *fn);
int dsystem_buff(const char *buff);

int InitConsole(const char *font, const char *background, int lines, int x, int y, int w, int h, int alpha);
void ShutdownConsole();

void DrawConsole();
int ToggleConsole();
void ShowConsole();
void HideConsole();
ConsoleInformation *GetConsole();


typedef struct Module {

    klibrary_t *lib;
	const char *fn;
    const char *name;
    int refcnt;
    int id;

} Module_t;


int InitModules();
void ShutdownModules();

Module_t *OpenModule(const char *fn);

int CloseModule(Module_t *m);

Item_list_t *GetModuleList();

Module_t *GetModuleById(int id);
Module_t *GetModuleByFileName(const char *fn);
Module_t *GetModuleByName(const char *name);

Module_t *VoidToModule(void *ptr);


int FileSize(const char *fn);
int FileExists(const char *fn);
int DirExists(const char *fn);
int PeriphExists(const char *name);

const char *relativeFilePath(char *rel, char *file);
int relativeFilePath_wb(char *buff, const char *rel, const char *file);
char *getFilePath(const char *file);
char *realpath(const char *path, char *resolved);


void ds_sleep(int ms);

SDL_Surface *GetScreen();
void SetScreen(SDL_Surface *new_screen);

int GetScreenWidth();
int GetScreenHeight();

void SDL_DS_SetWindow(int width, int height);
void SetScreenMode(int w, int h, float x, float y, float z);

void SDL_DS_AllocScreenTexture(SDL_Surface *screen);
void SDL_DS_FreeScreenTexture(int reset_pvr_memory);

pvr_ptr_t *GetScreenTexture();
void SetScreenTexture(pvr_ptr_t *txr);

void SetScreenOpacity(float opacity);
float GetScreenOpacity();
void SetScreenFilter(int filter);
void SetScreenVertex(float u1, float v1, float u2, float v2);

void DisableScreen();
void EnableScreen();
int ScreenIsEnabled();
void ScreenChanged();

void ScreenFadeIn();
void ScreenFadeOut();

void InitVideoThread();
void ShutdownVideoThread();

void LockVideo();
void UnLockVideo();
int VideoIsLocked();

int InitVideo(int w, int h, int bpp);
void ShutdownVideo();

void bf_print(int x, int y, char *str);
void ShowLogo();


/* Load PVR to a KOS Platform Independent Image */
int pvr_to_img(const char *filename, kos_img_t *rv);

/* Load PNG to a KOS Platform Independent Image */
int png_to_img(const char * filename, kos_img_t *rv);


typedef struct MouseCursor {
    
    SDL_Surface *bg;
    SDL_Surface *cursor;
    SDL_Rect src;
    SDL_Rect dst;
    int draw;

} MouseCursor_t;


/*
  Create cursor from file or surface.
*/
MouseCursor_t *CreateMouseCursor(const char *fn, SDL_Surface *surface);
void DestroyMouseCursor(MouseCursor_t *c);
void DrawMouseCursor(MouseCursor_t *c);
void SetActiveMouseCursor(MouseCursor_t *c);
MouseCursor_t *GetActiveMouseCursor();
void UpdateActiveMouseCursor();
void DrawActiveMouseCursor();


int InitGUI();
void ShutdownGUI();


/**
 * FAT filesystem
 */

int fs_SDC_init();
int fs_SDC_shutdown();
int fs_SDC_set_SPI_delay(char drv, int speed);

int fs_IDE_init();
int fs_IDE_shutdown();


int ide_init();
void ide_shutdown();
int ide_read(uint32 linear,uint32 numsects, void *bufptr);
int ide_write(uint32 linear,uint32 numsects, void *bufptr);
uint32 ide_num_sectors();


void spi_init();
void spi_shutdown();
void spi_set_delay(int delay);
int spi_get_delay();
void spi_cs_on(int cs);
void spi_cs_off(int cs);
void spi_send_byte(uint8 b);
uint8 spi_rec_byte();
uint8 spi_sr_byte(uint8 b);
uint8 spi_slow_sr_byte(uint8 b);
void spi_send_data(const uint8* data, uint16 data_len);
void spi_rec_data(uint8* buffer, uint16 buffer_len);