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


#ifdef	__PLATFORM_WINDOWS__
		#define	WIN32_LEAN_AND_MEAN
		#define NOGDI
		#include <windows.h>
#endif

		#include "squirrel_binding.h"
		#include "binding_helpers.h"
		#include "filesystem/filesystem.h"
		#include "filesystem/io_memory.h"
		#include "filesystem/io_cfile.h"
		#include "filesystem/io_handle.h"
		#include "rand/rand.h"
		#include "platform.h"

		using namespace GS;
		using namespace GS::Script;


//------------------------------------------------------------------------------
SQInteger			SystemGetClock(HSQUIRRELVM vm)		{
	__SQ_RETURNINT(Platform::Get().GetClock())		}
SQInteger			SystemGarbageCollect(HSQUIRRELVM vm)		{
	sq_collectgarbage(vm);
	__SQ_RETURN
}
SQInteger			SystemGetClockFrequency(HSQUIRRELVM vm)
{	__SQ_RETURNINT(Platform::Get().GetClockFrequency())	}
SQInteger			SystemGetLocale(HSQUIRRELVM vm)
{	__SQ_RETURNSTRING(/*Platform::Get().GetLocale()*/"STUB")	}
SQInteger			SystemGetPlatform(HSQUIRRELVM vm)
{	__SQ_RETURNSTRING(Platform::Get().GetName())	}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
SQInteger			SystemSeedRand(HSQUIRRELVM vm)
{
	__SQ_GETSINGLE(__SQ_GETINT(seed))
	Random::Seed(seed);
	__SQ_RETURN
}
SQInteger			SystemRand(HSQUIRRELVM vm)
{
	__SQ_GETSINGLE(__SQ_GETINT(range))
	__SQ_RETURNINT(Random::Rand(range));
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
SQInteger			SystemShowCursor(HSQUIRRELVM vm)
{
	__SQ_GETSINGLE(__SQ_GETBOOL(show))
#ifdef __PLATFORM_WINDOWS__
	ShowCursor(show);
#endif
	__SQ_RETURN
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
SQInteger			SystemSleep(HSQUIRRELVM vm)
{
	__SQ_GETSINGLE(__SQ_GETINT(ms))
	Platform::Get().Sleep(ms);
	__SQ_RETURN
}

//------------------------------------------------------------------------------
SQInteger			SystemSetProcessAffinity(HSQUIRRELVM vm)
{
	__SQ_GETSINGLE(__SQ_GETINT(num_thread))
		HANDLE process = GetCurrentProcess();
		DWORD_PTR processAffinityMask = 1 << 0;
		for (int i = 1; i < num_thread; ++i)
			processAffinityMask |= (1 << i);

		BOOL success = SetProcessAffinityMask(process, processAffinityMask);
	__SQ_RETURN
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
SQInteger			SystemMountLocalPath(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSTRING(mount_point)
	__SQ_GETSTRING(local_path)
	bool r = Platform::Get().io->Mount(new IO::CFile(local_path), mount_point);
	__SQ_GETEND
	__SQ_RETURNBOOL(r)
}
SQInteger			SystemHasMountPoint(HSQUIRRELVM vm)
{
	__SQ_GETSTART(1)
	__SQ_GETSTRING(mount_point)
	bool r = asbool(Platform::Get().io->GetIOSystem(mount_point));
	__SQ_GETEND
	__SQ_RETURNBOOL(r)
}
SQInteger			GetPathFromMountPoint(HSQUIRRELVM vm)
{
	__SQ_GETSTART(1)
	__SQ_GETSTRING(mount_point)
	__SQ_GETEND
	IO::Base* base = Platform::Get().io->GetIOSystem(mount_point);
	if(base == NULL)
		__SQ_RETURNSTRING("")
	else
		__SQ_RETURNSTRING(base->MapToAbsolute(""))
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
SQInteger			SystemLoadBindingPlugin(HSQUIRRELVM vm)
{
	__SQ_GETSTART(1)
	__SQ_GETSTRING(shared_lib_path)

	SquirrelVM *sq = (SquirrelVM *)sq_getforeignptr(vm);
	int code_error = 0;
	Script::BindingPluginManager::Plugin *plugin = sq->binding_plugins.LoadPlugin(shared_lib_path, &code_error);

	if	(plugin == NULL)
		return sq_throwerror(vm, "Failed to load binding library.");

	else
	{
		Script::IScriptBinding *binding = sq->binding_plugins.CreatePluginInterface(plugin);
		binding->RegisterBinding(*sq);
	}

	__SQ_GETEND
	__SQ_RETURNBOOL(true)
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void				RegisterSystemBinding(HSQUIRRELVM vm)
{
/*#
	Topic: System
#*/

/*#
	Section: System
	Desc: System functions
#*/
	/*#
		Func: SystemSleep
		Proto: void:int
		Desc: Sleep the current thread for a specified number of milliseconds.
	#*/
	sq_register(vm, SystemSleep, "SystemSleep", _SC(".i"));

	/*#
	Func: SystemSetProcessAffinity
	Proto: void:int
	Desc: Set the number of thread affinity for the process simulator.
	#*/
	sq_register(vm, SystemSetProcessAffinity, "SystemSetProcessAffinity", _SC(".i"));

	/*#
		Func: SystemGetClock
		Proto: int:
		Desc: Return the raw system clock.
	#*/
	sq_register(vm, SystemGetClock, "SystemGetClock", _SC("."));
	/*#
	Func: SystemGarbageCollect
	Proto: void:
	Desc: garbage collect.
	#*/
	sq_register(vm, SystemGarbageCollect, "SystemGarbageCollect", _SC("."));
	/*#
		Func: SystemGetClockFrequency
		Proto: int:
		Desc: Return the system clock frequency.
	#*/
	sq_register(vm, SystemGetClockFrequency, "SystemGetClockFrequency", _SC("."));
	/*#
		Func: SystemGetLocale
		Proto: string:
		Desc: Return the system language description in a string ("FR","EN","ES","NL","IT").
	#*/
	sq_register(vm, SystemGetLocale, "SystemGetLocale", _SC("."));
	/*#
		Func: SystemGetPlatform
		Proto: string:
		Desc: Return the current platform ("Win32", "Linux32", "Wii").
	#*/
	sq_register(vm, SystemGetPlatform, "SystemGetPlatform", _SC("."));

	/*#
		Func: SystemRand
		Proto: int:int range
		Desc: Return a random number between [0;range].
	#*/
	sq_register(vm, SystemRand, "SystemRand", _SC(".n"));
	/*#
		Func: SystemSeedRand
		Proto: void:int seed
		Desc: Initialize the random number sequence with a given seed.
	#*/
	sq_register(vm, SystemSeedRand, "SystemSeedRand", _SC(".n"));

	/*#
		Func: SystemShowCursor
		Proto: void:bool show
		Desc: Show/hide the platform cursor.
	#*/
	sq_register(vm, SystemShowCursor, "SystemShowCursor", _SC(".b"));

	/*#
		Func: SystemMountLocalPath
		Proto: bool:String local_path,String mount_point
		Desc: Mount a local path under a specific mount point.
		Example: SystemMountLocalPath("d:/test/", "@test/")		// "d:/test/a.jpg" can now be accessed as "@test/a.jpg".
	#*/
	sq_register(vm, SystemMountLocalPath, "SystemMountLocalPath", _SC(".ss"));
	/*#
		Func: SystemHasMountPoint
		Proto: bool:string mount_point
		Desc: Returns true if the specified mount point exists.
	#*/
	sq_register(vm, SystemHasMountPoint, "SystemHasMountPoint", _SC(".s"));	
	/*#
		Func: GetPathFromMountPoint
		Proto: string:string mount_point
		Desc: Returns path if the specified mount point exists.
	#*/
	sq_register(vm, GetPathFromMountPoint, "GetPathFromMountPoint", _SC(".s"));

	/*#
		Func: SystemLoadBindingPlugin
		Proto: bool:string library_path
		Desc: Load a script binding API from a shared library.
	#*/
	sq_register(vm, SystemLoadBindingPlugin, "SystemLoadBindingPlugin", _SC(".s"));

	/*#
		Enum: HardwareButton
		Values: HardwareButtonHome,HardwareButtonMenu,HardwareButtonBack
	#*/
	sq_pushstring(vm, "HardwareButtonHome", -1); sq_pushinteger(vm, 0); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "HardwareButtonMenu", -1); sq_pushinteger(vm, 1); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "HardwareButtonBack", -1); sq_pushinteger(vm, 2); sq_newslot(vm, -3, true);
}
//------------------------------------------------------------------------------
