/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#if __PLATFORM_NINTENDO_WII__


		#include "squirrel_binding.h"
		#include "binding_helpers.h"
		#include "uc_binding.h"

		#include <string.h>
		#include <math.h>

		#include <Revolution.h>
		#include <revolution/kpad.h>
		#include <revolution/sc.h>
		#include <revolution/arc.h>
		#include <revolution/cx.h>
		#include <revolution/tmcc/tmcc_jpeg.h>

		#include <revolution/sc.h>
		#include <revolution/os.h>
		#include <revolution/mem/allocator.h>
		#include <revolution/wpad.h>
		
		#include "Wii_platform.h"

//---------------------------------------------------------
WIIHome 			Wii::HomeMenu ATTRIBUTE_ALIGN(32);

nWiiMixer* 			Wii::Mixer = NULL;
WiiSaveMngr 		Wii::Save;
nWiiGXRenderer* 	Wii::Renderer = NULL;
GSFramework* 		Wii::Engine = NULL;
nProject* 			Wii::Project = NULL;
WIIWareStrap* 		Wii::Strap = NULL;	
nWiiAllocator 		Wii::MEM2_allocator;
nIOMemoryFS*		Wii::pMemory_fs = NULL;

unsigned int 		Wii::LastAudioUpdateTime = (u32)OSGetTick();
bool 				Wii::DisableAudioUpdate = false;
bool				Wii::VideoInited = false;
//---------------------------------------------------------

//---------------------------------------------------------
bool Wii::LoadingAudioUpdate()
//---------------------------------------------------------
{
	#define WII_LOADING_AUDIO_UPDATE_PERIOD_MS	(1000/20)
	#define WII_LOADING_AUDIO_UPDATE_SLEEP_MS	(2)

	if (DisableAudioUpdate)
		return;

    u32 currentTick = (u32)OSGetTick(); 
    u32 diffCSTime = OSTicksToMilliseconds( OSDiffTick( currentTick, LastAudioUpdateTime ) );
	
	if (diffCSTime >= WII_LOADING_AUDIO_UPDATE_PERIOD_MS) 
	{
		if (Wii::Mixer) 
		{
			Wii::Mixer->Update();
			OSSleepMilliseconds( WII_LOADING_AUDIO_UPDATE_SLEEP_MS );
			
//			OSReport("audio updated, delayMs=%d\n",diffCSTime);
		}
		LastAudioUpdateTime = (u32)OSGetTick();		
	}	
}

//---------------------------------------------------------
void Wii::EnableHomeMenu(bool value) 
//---------------------------------------------------------
{
	if (value)
		WIIHome::enableFlags &= ~WII_HOME_DISABLE_HOME_BUTTON;
	else
		WIIHome::enableFlags |= WII_HOME_DISABLE_HOME_BUTTON;	
}

//---------------------------------------------------------
void Wii::ForceReturnToMenuInsteadOfReset(bool value)
//---------------------------------------------------------
{
	WIIHome::forceReturnToMenuInsteadOfReset = value;	
}

//---------------------------------------------------------
bool Wii::EnableResetAndPowerButtons(bool enable, bool allowPostpone) 
//---------------------------------------------------------
{
	u32 f = WII_HOME_DISABLE_RESET_BUTTON | WII_HOME_DISABLE_POWER_BUTTON;
	bool res = !(WIIHome::enableFlags & f);
	
	if (!enable && allowPostpone) 
		f |= WII_HOME_ALLOW_POWER_POSTPONE | WII_HOME_ALLOW_RESET_POSTPONE;
	
	if (enable) 
	{
		WIIHome::enableFlags &= ~f;
		WIIHome::enableFlags &= ~WII_HOME_ALLOW_POWER_POSTPONE;
		WIIHome::enableFlags &= ~WII_HOME_ALLOW_RESET_POSTPONE;
	}		
	else
		WIIHome::enableFlags |= f;	
	return res;
}

//---------------------------------------------------------
float Wii::GetSquareRatioFor16_9() 
//---------------------------------------------------------
{
	// cf VI_library_book, page 47
	// 					Game Virtual Space	EFB 		XFB 		VI
	//NTSC, EURGB60 	832×456 			640×456 	640×456 	686×456
	//PAL 				832×456 			640×456 	640×542 	682×542	
	
	if (SCGetAspectRatio()!=SC_ASPECT_RATIO_16x9) {
		return(1.0f);
	}
	else {
		if (	(SCGetEuRgb60Mode() == SC_EURGB60_MODE_ON)
			||	(VIGetTvFormat()	!= VI_PAL)) {
			return(686.0f/832.0f);
		}
		else {
			return(682.0f/832.0f);
		}		
	}
	
	return (1.0f);
}

//---------------------------------------------------------
SQInteger			WiiStartHomeMenu(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	if (	!Wii::HomeMenu.IsActivated() 
		&& 	((Wii::HomeMenu.enableFlags & WII_HOME_DISABLE_HOME_BUTTON)==0)) {
		Wii::HomeMenu.Init( SCGetAspectRatio()==SC_ASPECT_RATIO_16x9, VIGetTvFormat() );
	}
	__SQ_RETURN
}


//---------------------------------------------------------
SQInteger			WiiEnableHomeMenu(HSQUIRRELVM vm)
//---------------------------------------------------------
{	
	__SQ_GETSTART(1)
	__SQ_GETBOOL(value)
	__SQ_GETEND	
	Wii::EnableHomeMenu(value);
	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiGetHomeMenuRunning(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_RETURNBOOL(Wii::HomeMenu.IsActivated() == 1)
}

//---------------------------------------------------------
SQInteger			WiiEnableResetAndPowerButtons(HSQUIRRELVM vm)
//---------------------------------------------------------
{	
	__SQ_GETSTART(1)
	__SQ_GETBOOL(value)
	__SQ_GETEND	
	Wii::EnableResetAndPowerButtons(value);
	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiIs16_9(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_RETURNBOOL(SCGetAspectRatio()==SC_ASPECT_RATIO_16x9)
}

//---------------------------------------------------------
SQInteger			WiiGetSquareRatioFor16_9(HSQUIRRELVM vm)
//---------------------------------------------------------
{	
	__SQ_RETURNFLOAT(Wii::GetSquareRatioFor16_9());	
	return 1;
}

//---------------------------------------------------------
SQInteger			WiiReturnToDataManager(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	WIIHome::PowerAndResetPreprocess();
	OSReturnToDataManager();
	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiInitStrap(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	if (Wii::Strap) {
		static const GXColor fg = {0x00, 0xff, 0xff, 0xff};
		static const GXColor bg = {0x00, 0x00, 0x00, 0x00};
		OSFatal ( fg, bg, "WiiInitStrap" );
	}	
	Wii::Strap = new WIIWareStrap();
	Wii::Strap->Init();
	__SQ_RETURN
}

extern GSFramework	*gEngine;

//---------------------------------------------------------
SQInteger			WiiDeInitStrap(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	if (Wii::Strap) {
		Wii::Strap->DeInit();
		delete Wii::Strap;
		Wii::Strap = NULL;
						
// a quoi servait ce code déja ???						
//		VISetBlack(TRUE);
//		for (s32 i=0;i<2;i++) {
//			gEngine->GetRenderer()->ShowFrame();		
//			VIWaitForRetrace();	
//		}		
//		VISetBlack(FALSE);
//		VIWaitForRetrace();		
	}
	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiDrawStrap(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	Wii::Strap->Draw();
	VIWaitForRetrace();	
	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiGetVersion(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	static const char noe[] = "NOE";
	static const char noa[] = "NOA";	
	__SQ_RETURNSTRING ((WiiErrorMngr::Version == WiiErrorMngr::VERSION_NOE) ? noe : noa);
}

//---------------------------------------------------------
SQInteger			WiiGetLastErrorStrId(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_RETURNSTRING (WiiErrorMngr::GetLastErrorStrId().c_str());
}

//---------------------------------------------------------
SQInteger			WiiGetLastErrorText(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_RETURNSTRING (WiiErrorMngr::GetLastErrorText(WiiErrorMngr::ForcedLocaleForGetLastErrorText).c_str());	
}

//---------------------------------------------------------
SQInteger			WiiGetOptionText(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_GETSTART(1)
	__SQ_GETSTRING(optionStrID)	
	const char* res = ((WiiErrorMngr::GetOptionText(optionStrID, WiiErrorMngr::ForcedLocaleForGetLastErrorText)).c_str());
	__SQ_GETEND
	
	__SQ_RETURNSTRING(res);
}

//---------------------------------------------------------
SQInteger			WiiSetGameTitle(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_GETSTART(1)
	__SQ_GETSTRING(title)
	WiiErrorMngr::SetGameTitle(title);
	__SQ_GETEND		
	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiSaveInit(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_GETSTART(3)
	__SQ_GETINT(nbMetafiles)
	__SQ_GETINT(saveSizeInBytes)
	__SQ_GETINT(saveIconNbPictures)
	__SQ_GETEND

	WiiSaveMngr::Init(nbMetafiles, saveSizeInBytes, saveIconNbPictures);

	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiSaveExists(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_RETURNBOOL (WiiSaveMngr::SaveFileExists());
}


//---------------------------------------------------------
SQInteger			WiiSaveSave(HSQUIRRELVM vm)
//---------------------------------------------------------
{	
#ifndef NDEBUG
//	#define DEBUG_RESET_WHILE_SAVING
//	#define DEBUG_POWER_WHILE_SAVING
#endif

#ifdef DEBUG_RESET_WHILE_SAVING
	WIIHome::reset_called = true;
#endif

#ifdef DEBUG_POWER_WHILE_SAVING
	WIIHome::power_called = true;
#endif
	
	WiiSaveMngr::Save();
	__SQ_RETURN	
}

/*
//---------------------------------------------------------
SQInteger			WiiSaveLoad(HSQUIRRELVM vm)
//---------------------------------------------------------
{
//	WiiSaveMngr::Save();
	__SQ_RETURN	
}
*/

//---------------------------------------------------------
SQInteger			WiiSaveSetMetafile(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(metafile, nMetaFile, typetag_Metafile)
	__SQ_GETINT(id)	
		WiiSaveMngr::SetMetafile(metafile, id);
	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiSaveGetMetafile(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_GETSTART(1)
	__SQ_GETINT(id)	
		nMetaFile* ptr = WiiSaveMngr::GetMetafile(id);
		__SQ_RETURNMANAGEDSAFEPTR(ptr, typetag_Metafile)	
	__SQ_GETEND
}

//---------------------------------------------------------
SQInteger			WiiSaveDelete(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	WiiSaveMngr::DeleteSaveFile();
	__SQ_RETURN	
}

//---------------------------------------------------------
SQInteger			WiiGameRestart(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	Wii::HomeMenu.PerformReset();
	__SQ_RETURN	
}


//---------------------------------------------------------
SQInteger			WiiDumpMemInfo(HSQUIRRELVM vm)
//---------------------------------------------------------
{
#if __ENABLE_ENGINE_LOG__
	u32 freeMem1 = MEMGetTotalFreeSizeForExpHeap(((nWiiAllocator *)MEM1_allocator.vacc)->heap);
	OSReport("Mem1 Free = %do, %.2fko, %.2fMo\n", freeMem1, freeMem1/1024.0f, freeMem1/(1024.0f*1024.0f));

	u32 freeMem2 = MEMGetTotalFreeSizeForExpHeap(Wii::MEM2_allocator.heap);
	OSReport("Mem2 Free = %do, %.2fko, %.2fMo\n", freeMem2, freeMem2/1024.0f, freeMem2/(1024.0f*1024.0f));
#endif	
	__SQ_RETURN
}

//---------------------------------------------------------
SQInteger			WiiRemoteDisconnect(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_GETSTART(1)
	__SQ_GETINT(id)	

	if (id >= WPAD_CHAN0 && id <= WPAD_CHAN3)
		WPADDisconnect(id);
	
	__SQ_RETURN
}

/*
//---------------------------------------------------------
SQInteger			WiiSetClearColor(HSQUIRRELVM vm)
//---------------------------------------------------------
{
	__SQ_GETSTART(3)
	__SQ_GETINT(r)
	__SQ_GETINT(g)
	__SQ_GETINT(b)
	__SQ_GETEND
	
	GXColor c;
	c.a = 255;
	c.r = r;
	c.g = g;
	c.b = b;
    GXSetCopyClear(c, GX_MAX_Z24);

	__SQ_RETURN
}
*/

//-------------------------------------------------------
void				RegisterWiiBinding(HSQUIRRELVM vm)
//-------------------------------------------------------
{
/*#
	Topic: Wii
	Desc: NINTENDO Wii specific binding
#*/

/*#
	Section: WiiHome
	Desc: Wii Home menu
#*/

	/*#
		Func: WiiEnableHomeMenu
		Proto: void:bool
		Desc: Enable or disables the home button.
	#*/
	sq_register(vm, WiiEnableHomeMenu, "WiiEnableHomeMenu", _SC(".b"));
	/*#
		Func: WiiGetHomeMenuRunning
		Proto: bool:void
		Desc: Returns the state of the Home menu.
	#*/
	sq_register(vm, WiiGetHomeMenuRunning, "WiiGetHomeMenuRunning", _SC("."));	
	/*#
		Func: WiiStartHomeMenu
		Proto: void:void
		Desc: Launches Home menu (only if it is enabled).
	#*/
	sq_register(vm, WiiStartHomeMenu, "WiiStartHomeMenu", _SC("."));
	/*#
		Func: WiiReturnToDataManager
		Proto: void:void
		Desc: Launches the Home menu (only if it is enabled).
	#*/
	sq_register(vm, WiiReturnToDataManager, "WiiReturnToDataManager", _SC("."));	

/*#
	Section: WiiStrap
	Desc: Wii strap screen functions
#*/

	/*#
		Func: WiiInitStrap
		Proto: void:void
		Desc: Initializes strap screen data.
	#*/
	sq_register(vm, WiiInitStrap, "WiiInitStrap", _SC("."));	

	/*#
		Func: WiiDeInitStrap
		Proto: void:void
		Desc: Uninitialize strap screen data.
	#*/
	sq_register(vm, WiiDeInitStrap, "WiiDeInitStrap", _SC("."));
	
	/*#
		Func: WiiDrawStrap
		Proto: void:void
		Desc: Draws strap screen data.
	#*/
	sq_register(vm, WiiDrawStrap, "WiiDrawStrap", _SC("."));

/*#
	Section: WiiSystem
	Desc: Wii system functions
#*/

	/*#
		Func: WiiEnableResetButton
		Proto: void:bool
		Desc: Enable or disables the reset/shutdown button.
	#*/
	sq_register(vm, WiiEnableResetAndPowerButtons, "WiiEnableResetAndPowerButtons", _SC(".b"));

	/*#
		Func: WiiIs16_9
		Proto: bool:void
		Desc: Returns true if the Wii system configuration is set to 16/9 mode.
	#*/
	sq_register(vm, WiiIs16_9, "WiiIs16_9", _SC("."));	

	/*#
		Func: WiiGetSquareRatioFor16_9
		Proto: float:void
		Desc: Returns the ratio to use to scale 2D images in order to have square pixels on any TV screen.
	#*/
	sq_register(vm, WiiGetSquareRatioFor16_9, "WiiGetSquareRatioFor16_9", _SC("."));	

	/*#
		Func: WiiGetVersion
		Proto: String:void
		Desc: Returns "NOE" (Europe) or "NOA" (America).
	#*/
	sq_register(vm, WiiGetVersion, "WiiGetVersion", _SC("."));	

	/*#
		Func: WiiGetLastErrorStrId
		Proto: String:void
		Desc: Returns ID of the last error, returns an empty string if none.
	#*/
	sq_register(vm, WiiGetLastErrorStrId, "WiiGetLastErrorStrId", _SC("."));

	/*#
		Func: WiiGetLastErrorText
		Proto: String:void
		Desc: Returns a localized string describing last error.
	#*/
	sq_register(vm, WiiGetLastErrorText, "WiiGetLastErrorText", _SC("."));

	/*#
		Func: WiiGetOptionText
		Proto: String:String error_id
		Desc: Returns a localized string describing a non blocking error option string ID.
	#*/
	sq_register(vm, WiiGetOptionText, "WiiGetOptionText", _SC(".s"));

	/*#
		Func: WiiSetGameTitle
		Proto: void:String title
		Desc: Sets the game title that may be displayed in Wii error screens
	#*/
	sq_register(vm, WiiSetGameTitle, "WiiSetGameTitle", _SC(".s"));

/*#
	Section: WiiSave
	Desc: Wii save system functions
#*/

	/*#
		Func: WiiSaveInit
		Proto: void:int nbMetafiles, int saveSizeInBytes, int saveIconNbPictures
		Desc: Initialize the Wii save system information (does not perform any read/write to NAND).
	#*/
	sq_register(vm, WiiSaveInit, "WiiSaveInit", _SC(".iii"));
	/*#
		Func: WiiSaveExists
		Proto: bool:void
		Desc: Returns TRUE if save data exists (does not perform any write to NAND).
	#*/
	sq_register(vm, WiiSaveExists, "WiiSaveExists", _SC("."));
	/*#
		Func: WiiSaveSave
		Proto: void:void
		Desc: Saves data to the Wii NAND memory (WiiSaveInit / WiiSaveAddMetafile must have been called before calling this function).
	#*/
	sq_register(vm, WiiSaveSave, "WiiSaveSave", _SC("."));

	/*#
		Func: WiiSaveLoad
		Proto: void:void
		Desc: TBD (WiiSaveInit / WiiSaveSetMetafile must have been called before calling this function).
	#*/
//	sq_register(vm, WiiSaveLoad, "WiiSaveLoad", _SC("."));

	/*#
		Func: WiiSaveSetMetafile
		Proto: void:Metafile,int id
		Desc: TBD
	#*/
	sq_register(vm, WiiSaveSetMetafile, "WiiSaveSetMetafile", _SC(".xi"));	

	/*#
		Func: WiiSaveGetMetafile
		Proto: Metafile:int id
		Desc: TBD
	#*/
	sq_register(vm, WiiSaveGetMetafile, "WiiSaveGetMetafile", _SC(".i"));

	/*#
		Func: WiiSaveDelete
		Proto: void:void
		Desc: deletes a game save data & save banner
	#*/
	sq_register(vm, WiiSaveDelete, "WiiSaveDelete", _SC("."));

	/*#
		Func: WiiGameRestart
		Proto: void:void
		Desc: restarts the game (like pressing reset ...)
	#*/
	sq_register(vm, WiiGameRestart, "WiiGameRestart", _SC("."));

	/*
		Func: WiiSetClearColor
		Proto: void:int r,int g,int b
		Desc: changes the wii clear color
	*/
	//sq_register(vm, WiiSetClearColor, "WiiSetClearColor", _SC(".iii"));	
	
	/*#
		Func: WiiDumpMemInfo
		Proto: void:void
		Desc: TBD
	#*/
	sq_register(vm, WiiDumpMemInfo, "WiiDumpMemInfo", _SC("."));

	/*#
		Func: WiiRemoteDisconnect
		Proto: void:int id
		Desc: TBD
	#*/
	sq_register(vm, WiiRemoteDisconnect, "WiiRemoteDisconnect", _SC(".i"));	
}


#endif
