#include <GOSScript\GOSScriptHeaders.hpp>
#include <GameOS\ToolOS.hpp>

HGOSHEAP clientHeap[8];
HGOSHEAP testHeap;
DWORD totalAlloc = 0;
double timeStart = 0.0;
double timeEnd = 0.0;

DWORD timeDiff = 0;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall InitializeGameEngine()
{
	//
	//---------------------------
	// Start the Script Processor
	//---------------------------
	//
	totalAlloc = 0;
	timeStart = 0.0;
	timeEnd = 0.0;
	timeDiff = 0;
	gosScript_InitializeProcessor();

	gosScript_RegisterVariable("totalAlloc", &totalAlloc,GOSVAR_INT, 0, 0);
	gosScript_RegisterVariable("timeDiff", &timeDiff,GOSVAR_INT, 0, 0);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall DoGameLogic()
{
//
// Check at least 4 byte aligntment working correctly
//
	void* fred=gos_Malloc( 20 );
	void* john=gos_Malloc( 20480 );
	gosASSERT( 0==((int)fred&3) && 0==((int)john&3) );
	gos_Free( fred );
	gos_Free( john );

	// description screen.
	gosScript_ExecuteScript("Assets\\Scripts\\TestMemory.script",0x2000,0);

	timeStart = gos_GetHiResTime();

	gos_srand( 0x12345678 );			// Always use same random sequence

	// allocated screen.
	testHeap = gos_CreateMemoryHeap( "Parent Test Heap", 0, ParentClientHeap );

	clientHeap[ 0 ] = gos_CreateMemoryHeap( "Heap 1", 0, testHeap );
	clientHeap[ 1 ] = gos_CreateMemoryHeap( "Heap 2", 0, testHeap );
	clientHeap[ 2 ] = gos_CreateMemoryHeap( "Heap 3", 0, testHeap );
	clientHeap[ 3 ] = gos_CreateMemoryHeap( "Heap 4", 0, testHeap );
	clientHeap[ 4 ] = gos_CreateMemoryHeap( "Heap 5", 0, testHeap );
	clientHeap[ 5 ] = gos_CreateMemoryHeap( "Heap 6", 0, testHeap );
	clientHeap[ 6 ] = gos_CreateMemoryHeap( "Heap 7", 0, testHeap );
	clientHeap[ 7 ] = gos_CreateMemoryHeap( "Heap 8", 0, testHeap );

	do 	
	{
		DWORD heapToUse = gos_rand() & 7;
		DWORD amt = 1 + (gos_rand() & ((1<<(heapToUse+5))-1));
		totalAlloc += amt;
		gos_Malloc( amt , clientHeap[ heapToUse ] );
	} while (totalAlloc < 100000000);

	// how long did the alloc take?
	timeEnd = gos_GetHiResTime();
	timeDiff = (DWORD) ((timeEnd - timeStart)*100);

	gosScript_ExecuteScript("Assets\\Scripts\\TestMemory1.script",0x2000,0);

	//
	// Here's an example of heap checking silently...
	//
	gos_WalkMemoryHeap(0, false);

	timeStart = gos_GetHiResTime();

	gos_DestroyMemoryHeap(clientHeap[7], false);
	clientHeap[7] = 0;
	gos_DestroyMemoryHeap(clientHeap[6], false);
	clientHeap[6] = 0;
	gos_DestroyMemoryHeap(clientHeap[5], false);
	clientHeap[5] = 0;
	gos_DestroyMemoryHeap(clientHeap[4], false);
	clientHeap[4] = 0;
	gos_DestroyMemoryHeap(clientHeap[3], false);
	clientHeap[3] = 0;
	gos_DestroyMemoryHeap(clientHeap[2], false);
	clientHeap[2] = 0;
	gos_DestroyMemoryHeap(clientHeap[1], false);
	clientHeap[1] = 0;
	gos_DestroyMemoryHeap(clientHeap[0], false);
	clientHeap[0] = 0;
	gos_DestroyMemoryHeap(testHeap, false);
	testHeap = 0;

	// how long did the dealloc take?
	timeEnd = gos_GetHiResTime();
	timeDiff = (DWORD) ((timeEnd - timeStart)*100);

	gosScript_ExecuteScript("Assets\\Scripts\\TestMemory2.script",0x2000,0);

	gos_TerminateApplication();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall SkunkworksUpdateDisplay()
{
	// let gosScript do it's thing, instead...
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall TerminateGameEngine()
{
	if (testHeap)
		gos_DestroyMemoryHeap(testHeap, false);
	testHeap = 0;
	clientHeap[7] = 0;
	clientHeap[6] = 0;
	clientHeap[5] = 0;
	clientHeap[4] = 0;
	clientHeap[3] = 0;
	clientHeap[2] = 0;
	clientHeap[1] = 0;
	clientHeap[0] = 0;


	//
	//--------------------------
	// Stop the Script Processor
	//--------------------------
	//
	gosScript_UnregisterVariable("timeDiff");
	gosScript_UnregisterVariable("totalAlloc");
	gosScript_ShutdownProcessor();

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall GetGameOSEnvironment(char* CommandLine)
{
	CommandLine = CommandLine;
	Environment.applicationName			= "Test Memory";
	Environment.screenWidth				= 640;
	Environment.screenHeight			= 480;
	Environment.fullScreen				= 0;
	Environment.bitDepth				= 16;
	Environment.debugLog				= "";
	Environment.spew					= "";
	Environment.memoryTraceLevel		= 1;
	Environment.TimeStampSpew			= 0;
	Environment.UpdateRenderers			= SkunkworksUpdateDisplay;
	Environment.DoGameLogic				= DoGameLogic;
	Environment.InitializeGameEngine	= InitializeGameEngine;
	Environment.TerminateGameEngine		= TerminateGameEngine;
	Environment.soundChannels			= 16;

	Environment.FullScreenDevice		= 0;
	Environment.fullScreen				= 0;
	Environment.AntiAlias				= 0;			// true/false - Enable full screen antialiasing
	Environment.Renderer				= 0;
																																				   
//
// Texture infomation
//

	Environment.Texture_S_256			= 1;
	Environment.Texture_S_128			= 1;
	Environment.Texture_S_64			= 1;
	Environment.Texture_S_32			= 1;
	Environment.Texture_S_16			= 1;

	Environment.Texture_K_256			= 1;
	Environment.Texture_K_128			= 1;
	Environment.Texture_K_64			= 1;
	Environment.Texture_K_32			= 1;
	Environment.Texture_K_16			= 1;

	Environment.Texture_A_256			= 1;
	Environment.Texture_A_128			= 1;
	Environment.Texture_A_64			= 1;
	Environment.Texture_A_32			= 1;
	Environment.Texture_A_16			= 1;

	Environment.RaidCustomFields		= "AssignedTo=andyg;Project=GameOS;Client=GameOS;Area=Memory Manager;GOSRaid=Yes"; 
	Environment.RaidDataSource			= "GameTech :Raid4";
	Environment.RaidFilePath			= "\\\\aas1\\coretech\\Test\\Raid\\Exceptions";
}

int _stdcall Dealloc(void * inst, int args, void * arg[16])
{
	args;
	inst;
	arg;
	return 0;
}