#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pspdisplay.h>
#include <pspnet_inet.h>
#include <pspnet_apctl.h>
#include <pspnet_resolver.h>
#include <psputility.h>
#include <netinet/in.h>
#include <kubridge.h>
#include <sys/select.h>
#include <pspctrl.h>
#include <errno.h>
#include <math.h>
#include <psputility.h>
#include <pspgu.h>
#include <pspgum.h>
#include <pspjpeg.h>
#include <oslib/oslib.h>
#include "lua.h"
#include "lauxlib.h"
#include "mikmod.h"

PSP_MODULE_INFO("Luamin", 0, 0, 1);
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU);
PSP_HEAP_SIZE_KB(-2*1024);
//PSP_MAIN_THREAD_PRIORITY(0x8);
#define printf	pspDebugScreenPrintf
//Lua Functions
extern void screen_init(L);
extern void image_init(L);
extern void color_init(L);
extern void timer_init(L);
extern void control_init(L);
extern void lua3d_init(L);
extern void sys_init(L);
extern void sound_init(L);
extern void net_init(L);
extern void font_init(L);
extern void StopMp3(void);
extern void ShowMessageDialog(const char *message, int enableYesno);
extern void runebootfile(char *path);
static lua_State *L;
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
	StopMp3();
	// Unload modules
	//osl_quit = 1;
	/*if (mikModThreadID > 0)
  	{
    		SceUInt timeout = 100000;
    		sceKernelWaitThreadEnd(mikModThreadID, &timeout);
    		sceKernelDeleteThread(mikModThreadID);
		Player_Stop();
		MikMod_Exit();
  	}*/
		sceKernelExitGame();
	return 0;
}
/* Callback thread */
static int CallbackThread(SceSize args, void *argp)
{
   int cbid;

   cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
   sceKernelRegisterExitCallback(cbid);

   sceKernelSleepThreadCB();

   return 0;
}

/* Sets up the callback thread and returns its thread id */
static int SetupCallbacks(void)
{
   int thid = 0;

   thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
   if(thid >= 0)
   {
      sceKernelStartThread(thid, 0, 0);
   }
   return thid;
}
static char path[256];
static char script[256];
static char driver[256];
static char eboot[256];
/*static char loadlib[256]*/;
static SceUID driverint(char *path)
{
    u32 loadResult;
    int status;
    loadResult = kuKernelLoadModule(path, 0, NULL);
    sceKernelStartModule(loadResult, 0, NULL, &status, NULL);
    return loadResult;
}
/*static int done = 0;
int AudioChannelThread(SceSize args, void *argp)
{
  while (!done)
  {
    MikMod_Update();
    // We have to sleep here to allow other threads a chance to process.
    // with no sleep this thread will take over when the output is disabled via MikMod_DisableOutput()
    // co-operative threading sucks bigtime...
    sceKernelDelayThread(15000);
  }
  return 0;
}
static void Music_init()
{
MikMod_InitThreads();
MikMod_RegisterAllDrivers();
MikMod_RegisterAllLoaders();
md_mode = DMODE_16BITS|DMODE_STEREO|DMODE_SOFT_MUSIC; 
md_reverb = 0;
md_pansep = 128;
MikMod_Init("");
MikMod_SetNumVoices(-1, 8);
mikModThreadID = sceKernelCreateThread("MikMod" ,AudioChannelThread,0x12,0x10000,0,NULL);
sceKernelStartThread(mikModThreadID, 0 , NULL);
}*/
int main(void)
{
//Music_init();
sprintf(driver,"%s/syslib.prx",path);
driverint(driver);
sprintf(driver,"%s/siolib.prx",path);
driverint(driver);
getcwd(path, 256);
oslInit(1);
oslInitGfx(OSL_PF_8888, 1);
sceUtilityLoadNetModule(PSP_NET_MODULE_ADHOC);
sceUtilityLoadNetModule(PSP_NET_MODULE_COMMON);
sceUtilityLoadNetModule(PSP_NET_MODULE_INET);
sceUtilityLoadNetModule(PSP_NET_MODULE_PARSEURI);
sceUtilityLoadNetModule(PSP_NET_MODULE_PARSEHTTP);
sceUtilityLoadNetModule(PSP_NET_MODULE_HTTP);
sceUtilityLoadNetModule(PSP_NET_MODULE_SSL);
sceUtilityLoadModule(PSP_MODULE_AV_AVCODEC);
sceUtilityLoadModule(PSP_MODULE_AV_MP3);
SetupCallbacks();
L = lua_open();
luaL_openlibs(L);
screen_init(L);
image_init(L);
color_init(L);
timer_init(L);
control_init(L);
lua3d_init(L);
sys_init(L);
sound_init(L);
net_init(L);
font_init(L);
sprintf(script,"%s/script.lua",path);
int s = luaL_loadfile(L, script);	
	if (s == 0) {
		s = lua_pcall(L, 0, LUA_MULTRET, 0);
	}
	if (s) {
		scePowerSetClockFrequency(333,333,166);
		char errbuf[512];
		char msgbuf[512];
		sprintf(errbuf,"An error has occured.\n%s\nDo you wish to enable the USB?",lua_tostring(L, -1));
		ShowMessageDialog(errbuf,1);
		if(oslGetDialogButtonPressed() == PSP_UTILITY_MSGDIALOG_RESULT_YES){
			oslInitUsbStorage();
			oslStartUsbStorage();
		}
		sprintf(msgbuf,"%s\nClose to restart the program",lua_tostring(L, -1));
		ShowMessageDialog(msgbuf,0);
		scePowerSetClockFrequency(222,222,111);
		oslStopUsbStorage();
		oslDeinitUsbStorage();
		lua_pop(L, 1); // remove error message
		sprintf(eboot,"%s/EBOOT.PBP",path);
		runebootfile(eboot);
	}
lua_close(L);
sceKernelSleepThread();
return 0;
}