#include <GameOS\GameOS.hpp>
#include <stdio.h>
#include <memory.h>


HGOSFONT3D font3d = 0;
float mx,my; // mouse pos
DWORD buttons;
int pWheelDelta;
DWORD deBounce;
DWORD deBounce1;
bool playing0 = false;
bool playing1 = false;
HGOSFORCEEFFECT fe1 = 0;
HGOSFORCEEFFECT fe2 = 0;
HGOSFORCEEFFECT fe3 = 0;
HGOSFORCEEFFECT fe4 = 0;

void LoadEffect(int val);

char FFEs[][32] =
{
"ammoout.ffe",
"arrow.ffe",
"bazooka.ffe",
"blowout.ffe",
"bltrifle.ffe",
"cannon.ffe",
"car1.ffe",
"car2.ffe",
"car3.ffe",
"chaina.ffe",
"chainb.ffe",
"chainc.ffe",
"chainsaw.ffe",
"click1.ffe",
"click2.ffe",
"crosbow1.ffe",
"crosbow2.ffe",
"csawing1.ffe",
"csawing2.ffe",
"csawing3.ffe",
"csawing4.ffe",
"dirt1.ffe",
"dirt2.ffe",
"dirt3.ffe",
"dirt4.ffe",
"dribble1.ffe",
"dribble2.ffe",
"energy1.ffe",
"energy2.ffe",
"enginea.ffe",
"engineb.ffe",
"enginec.ffe",
"engined.ffe",
"flame.ffe",
"gatling.ffe",
"guna.ffe",
"gunb.ffe",
"helia.ffe",
"helib.ffe",
"helic.ffe",
"helid.ffe",
"idling.ffe",
"jump.ffe",
"land1.ffe",
"land2.ffe",
"laser1.ffe",
"laser2.ffe",
"laser3.ffe",
"laser4.ffe",
"laser5.ffe",
"laser6.ffe",
"lightnng.ffe",
"lsaber.ffe",
"machineg.ffe",
"magneta.ffe",
"magnetb.ffe",
"magnetc.ffe",
"mech1.ffe",
"mech2.ffe",
"mech3.ffe",
"missile.ffe",
"offroad1.ffe",
"offroad2.ffe",
"offroad3.ffe",
"offroad4.ffe",
"paved1.ffe",
"paved2.ffe",
"paved3.ffe",
"paved4.ffe",
"pistol.ffe",
"plasma1.ffe",
"plasma2.ffe",
"plasma3.ffe",
"pogoa.ffe",
"pogob.ffe",
"punch.ffe",
"punched1.ffe",
"punched2.ffe",
"rocket1.ffe",
"rocket2.ffe",
"rolling.ffe",
"running1.ffe",
"running2.ffe",
"running3.ffe",
"sabera.ffe",
"saberb.ffe",
"saberc.ffe",
"secdoor1.ffe",
"secdoor2.ffe",
"shotgun1.ffe",
"shotgun2.ffe",
"shotgun3.ffe",
"skatea.ffe",
"skateb.ffe",
"sliding.ffe",
"swim1.ffe",
"swim2.ffe",
"swim3.ffe",
"takeoff1.ffe",
"takeoff2.ffe",
"takeoff3.ffe",
"trampa.ffe",
"trampb.ffe",
"trampc.ffe",
"turbulen.ffe",
"walking.ffe",
"wall.ffe",
"windgust.ffe",
"wsheer1.ffe",
"wsheer2.ffe",
} ;

int sel_FFE = 34;
int num_effects = 0;
float axis_value[12];
DWORD button_value[32];

gosJoystick_Info ji;
gosJoystick_ForceEffect gfeConstant;
gosJoystick_ForceEffect gfeRamp;
gosJoystick_ForceEffect gfePeriodic;

int totalJoysticks = 0;
int displayedJoystick = 0;
void EasyDrawLine( int X0, int Y0, int X1, int Y1, DWORD Color );


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall InitializeGameEngine()
{
	/////////////////////////////////////////////////////
	// this functionality has been stubbed out of GameOS
	gos_EnableSetting( gos_Set_NumLockMode, 0);
	gos_EnableSetting( gos_Set_CapsLockMode, 1);
	gos_EnableSetting( gos_Set_ScrollLockMode, 2);
	/////////////////////////////////////////////////////

	font3d = gos_LoadFont( "assets\\graphics\\fonttexture.tga");
	totalJoysticks = gosJoystick_CountJoysticks();
	num_effects = sizeof(FFEs)/32;
	
	displayedJoystick=0;
	if( totalJoysticks )
	{
		gosJoystick_SetPolling( displayedJoystick, true );
		gosJoystick_GetInfo( displayedJoystick, &ji );
	}
	
	
	char tmp[64];
	if (ji.bIsForceFeedback)
	{
		sprintf(tmp, "assets\\feedback\\%s", FFEs[sel_FFE]);
		gosJoystick_LoadEffect(&fe4, 0, tmp );
		sprintf(tmp, "assets\\feedback\\%s", FFEs[12]);
		gosJoystick_LoadEffect(&fe1, 0, tmp );


		//
		// A user-defined, user-controlled effect
		//
		memset(&gfeConstant, 0, sizeof(gosJoystick_ForceEffect));
		gfeConstant.eType = gosForce_Constant;
		gfeConstant.bAffectedAxes[JOY_XAXIS] = gfeConstant.bAffectedAxes[JOY_YAXIS] = true;
		gfeConstant.fMagnitude = 1.0f;
		gfeConstant.fDurationSec = 1.0;
		gfeConstant.fScale = 1.0f;
		gfeConstant.fXOrigin = 0;
		gfeConstant.fYOrigin = 0; 
		gosJoystick_CreateEffect(&fe2, 0, &gfeConstant);

	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall DoGameLogic()
{
	float x,y;
	gos_GetMouseInfo( &x, &y, 0, 0, &pWheelDelta, &buttons );
	mx = (x*Environment.screenWidth);
	my = (y*Environment.screenHeight);

	gfeConstant.fXOrigin = (float) x*Environment.screenWidth - (Environment.screenWidth / 2) ;
	gfeConstant.fYOrigin = (float) y*Environment.screenHeight - (Environment.screenHeight / 2) ;
	DWORD key = gos_GetKey()&0xff;

	if( key=='R' || key=='r' )
	{
		totalJoysticks = gosJoystick_CountJoysticks();

		if( displayedJoystick>totalJoysticks )
			displayedJoystick=totalJoysticks-1;
	}


	if( totalJoysticks )
	{
		if( key=='+' )
		{
			gosJoystick_SetPolling(displayedJoystick, false);
			displayedJoystick++;
			if (displayedJoystick >= totalJoysticks)
				displayedJoystick = 0;
			gosJoystick_SetPolling(displayedJoystick, true);
			gosJoystick_GetInfo(displayedJoystick, &ji);
		}

		if( key=='-' )
		{
			gosJoystick_SetPolling(displayedJoystick, false);
			displayedJoystick--;
			if (displayedJoystick < 0)
				displayedJoystick =  totalJoysticks -1;
			gosJoystick_SetPolling(displayedJoystick, true);
			gosJoystick_GetInfo(displayedJoystick, &ji);
		}
		if (ji.bIsForceFeedback)
		{
			if (gosJoystick_ButtonStatus(displayedJoystick, 2) == true)
			{
				gosJoystick_UpdateEffect(fe2, &gfeConstant);
				gosJoystick_PlayEffect(fe2,1);
			}

			if (gosJoystick_IsEffectPlaying(fe4))
				playing0 = true;
			else
			{
				playing0 = false;
				if (gosJoystick_ButtonStatus(displayedJoystick,0) == true)
				{
					if (!deBounce)
					{
						if (!playing0)
						{
							playing0 = true;
							gosJoystick_PlayEffect(fe4);
						}
						deBounce = 1;
					}
				}
				else
				{
					playing0 = false;
					deBounce = 0;
				}
			}
			if (gosJoystick_IsEffectPlaying(fe1))
				playing1 = true;
			else
			{
				playing1 = false;
				if (gosJoystick_ButtonStatus(displayedJoystick,1) == true)
				{
					if (!deBounce1)
					{
						if (!playing1)
						{
							playing1 = true;
							gosJoystick_PlayEffect(fe1);
						}
						deBounce1 = 1;
					}
				}
				else
				{
					playing1 = false;
					deBounce1 = 0;
				}
			}
		}
		// get all the info necessary for display
		for(int i = 0; i < 12; i++)
		{
			if (ji.bAxisValid & (1<<i))
			{
				axis_value[i] = gosJoystick_GetAxis(displayedJoystick, (enum GOSJoystickAxis) i);
			}
		}
		for(i = 0; i < (int) ji.nButtons; i++)
		{
			button_value[i] = gosJoystick_ButtonStatus(displayedJoystick, i);
		}

	}
	if (mx > 360 && mx < 760 && my > 16 && my < 16*33)
	{
		int column = (((int)mx)-360) / 100;
		int row = (((int)my)-16)/ 16;

		if (column * 32 + row < num_effects)
		{
			if (gos_GetKeyStatus(KEY_LMOUSE) == KEY_PRESSED)
			{
				sel_FFE = column*32+row;
				if (ji.bIsForceFeedback)
					LoadEffect(sel_FFE);
			}
		}
	}
}

void __stdcall UpdateDisplay()
{
	//--------------
	// set viewport
	//--------------
	gos_SetupViewport(
		false,	//bool FillZ,
		1.0f,		//float ZBuffer,
		true,	//bool FillBG,
		0x00000000,	//DWORD newBGColor,
		1.0f,		//float top,
		1.0f,		//float left,
		0.0f,		//float bottom,
		0.0f		//float right
	);

	// display possible effects
	for(int i=0; i < 32; i++)
	{
		gos_TextSetPosition( 360, 16 + i*16);
		gos_TextSetAttributes( font3d, 0xff7f0000, -8, true, true, 0, 0 );
		gos_TextDraw( FFEs[i] );
	}

	for(i=32; i < 64; i++)
	{
		gos_TextSetPosition( 460, 16 + (i-32)*16);
		gos_TextSetAttributes( font3d, 0xff7f0000, -8, true, true, 0, 0 );
		gos_TextDraw( FFEs[i] );
	}

	for(i=64; i < 96; i++)
	{
		gos_TextSetPosition( 560, 16 + (i-64)*16);
		gos_TextSetAttributes( font3d, 0xff7f0000, -8, true, true, 0, 0 );
		gos_TextDraw( FFEs[i] );
	}

	for(i=96; i < 110; i++)
	{
		gos_TextSetPosition( 660, 16 + (i-96)*16);
		gos_TextSetAttributes( font3d, 0xff7f0000, -8, true, true, 0, 0 );
		gos_TextDraw( FFEs[i] );
	}

	// highlight current FFE
	gos_TextSetPosition(360 + ((sel_FFE/32)*100), 16 + (16*(sel_FFE % 32)));
	gos_TextSetAttributes( font3d, 0xffff0000, -8, true, true, 1, 0 );
	gos_TextDraw(FFEs[sel_FFE]);

	// highlight FFE under mouse...
	if (mx > 360 && mx < 760 && my > 16 && my < 16*33)
	{
		int column = ((int)(mx-360)) / 100;
		int row = (((int)my)-16)/ 16;

		if (column * 32 + row < num_effects)
		{
			gos_TextSetPosition(360 + column*100, 16 + (row*16));
			gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, 1, 0 );
			gos_TextDraw(FFEs[column*32+row]);
		}
	}



	int numberReadouts = 0;
	gos_TextSetPosition( 0, 0);
	gos_TextSetAttributes( font3d, 0xffff0000, -16, true, true, 1, 0 );
	gos_TextDraw( "Test Input" );


	gos_TextSetPosition( 10, Environment.screenHeight-86 );
	gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, 1, 0 );
	gos_TextDraw( " 'R' to re-detect joysticks" );

	gos_TextSetPosition( 10, 32);
	gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, 1, 0 );
	gos_TextDraw( "Total Joysticks found %d", totalJoysticks);


	if (totalJoysticks)
	{
		if( totalJoysticks>1 )
		{
			gos_TextSetPosition( 10, Environment.screenHeight-64 );
			gos_TextSetAttributes( font3d, 0xffffffff, -12, true, true, 1, 0 );
			gos_TextDraw( " '+' or '-' to change joystick device" );
		}

		gos_TextSetPosition( 10, 48);
		gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, 1, 0 );
		gos_TextDraw( "Current Joystick %d : %s", displayedJoystick, ji.lpstrName );
		
		gos_TextSetPosition( 10, 80);
		gos_TextDraw
			( 
				"# Axes: %d, # Sliders: %d, # POVs: %d, # Buttons: %d",
				ji.nAxes,
				ji.nSliders,
				ji.nPOVs,
				ji.nButtons
			);
		for(int i = 0; i < 6; i++)
		{
			if (ji.bAxisValid & (1<<i))
			{
				gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, true, true );
				EasyDrawLine( 5 ,100+numberReadouts*16, 205,100+numberReadouts*16, 0xffffffff );
				gos_TextSetPosition( 100 + ((int) (100.0f * axis_value[i])), 94 + numberReadouts*16 );
				gos_TextDraw("o");
				gos_TextSetAttributes( font3d, 0xffff0000, -8, true, true, true, false );
				gos_TextSetPosition( 210, 94+numberReadouts*16 );
				switch(i)
				{
				case 0:
					{
						gos_TextDraw("X Axis ( %f )", axis_value[i] );
					}
					break;
				case 1:
					{
						gos_TextDraw("Y Axis ( %f )", axis_value[i] );
					}
					break;
				case 2:
					{
						gos_TextDraw("Z Axis ( %f )", axis_value[i] );
					}
					break;
				case 3:
					{
						gos_TextDraw("RX Axis ( %f )", axis_value[i] );
					}
					break;
				case 4:
					{
						gos_TextDraw("RY Axis ( %f )", axis_value[i] );
					}
					break;
				case 5:
					{
						gos_TextDraw("RZ Axis ( %f )", axis_value[i] );
					}
					break;
				}
				numberReadouts++;
			}
		}
		for(i = 6; i < 8; i++)
		{
 			if (ji.bAxisValid & (1<<i))
			{
				gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, true, true );
				EasyDrawLine( 5 ,100+numberReadouts*16, 205,100+numberReadouts*16, 0xffffffff );
				gos_TextSetPosition( 100 + ((int) (100.0f * axis_value[i])), 94 + numberReadouts*16 );
				gos_TextDraw("o");
				gos_TextSetAttributes( font3d, 0xffff0000, -8, true, true, true, false );
				gos_TextSetPosition( 210, 94+numberReadouts*16 );
				gos_TextDraw("Slider %d ( %f )", i - 5, axis_value[i] );
				numberReadouts++;
			}
		}
		for(i = 8; i < 12; i++)
		{
 			if (ji.bAxisValid & (1<<i))
			{
				gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, true, 0 );
				EasyDrawLine( 5 ,100+numberReadouts*16, 205,100+numberReadouts*16, 0xffffffff );
				gos_TextSetPosition( 100 + ((int) (100.0f * axis_value[i])), 94 + numberReadouts*16 );
				gos_TextDraw("o");
				gos_TextSetAttributes( font3d, 0xffff0000, -8, true, true, true, false );
				gos_TextSetPosition( 210, 94+numberReadouts*16 );
				gos_TextDraw( "POV %d ( %f )", i-7,  axis_value[i]);
				numberReadouts++;
			}
		}
		gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, true, false );
		gos_TextSetPosition( 210, 94+numberReadouts*16 );
		gos_TextDraw( "Buttons (%d - %d)", 0, ji.nButtons-1);
		gos_TextSetPosition( 5, 94+numberReadouts*16 );
		for(i = 0; i < (int) ji.nButtons; i++)
		{
			if (button_value[i])
				gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, true, false );
			else
				gos_TextSetAttributes( font3d, 0xffff0000, -8, true, true, true, false );
			gos_TextDraw("o");
		}
	}
	else
	{
		gos_TextSetPosition( 0, 64);
		gos_TextSetAttributes( font3d, 0xffff0000, -16, true, true, true, false );
		gos_TextDraw( "No joysticks found on system." );
	}
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Do the mouse next

	// draw the mouse.
	gos_TextSetPosition((int)mx-7,(int)my-7);
	gos_TextSetAttributes( font3d, 0xffffff00, -16, false, false, true, false );
	gos_TextDraw("X");

	gos_TextSetAttributes( font3d, 0xffff0000, -16, true, true, true, false );
	gos_TextSetPosition(0, 380);
	gos_TextDraw("Mouse Informaton:");
	gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, true, false );
	gos_TextSetPosition(10, 400);
	char mouseInfo[32];
	sprintf(mouseInfo, "Location: (%.2f, %.2f)\n", mx, my);
	gos_TextDraw(mouseInfo);
	gos_TextSetPosition(10, 412);
	sprintf(mouseInfo, "Buttons:  ");
	gos_TextDraw(mouseInfo);
	for(i=0; i < 5; i++)
	{
		if (buttons & (1 << i))
		{
			gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, true, false );
		}
		else
		{
			gos_TextSetAttributes( font3d, 0xffff0000, -8, true, true, true, false );
		}
		gos_TextDraw("o");
	}
	gos_TextSetPosition(10, 424);
	gos_TextSetAttributes( font3d, 0xffffffff, -8, true, true, true, false );
	sprintf(mouseInfo, "Wheel:     %d\n", pWheelDelta);
	gos_TextDraw(mouseInfo);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall TerminateGameEngine()
{
	if( fe1 )
	{
		gosJoystick_DestroyEffect(&fe1);
		fe1=0;
	}
	if( fe2 )
	{
		gosJoystick_DestroyEffect(&fe2);
		fe2=0;
	}
	if( fe3 )
	{
		gosJoystick_DestroyEffect(&fe3);
		fe3=0;
	}
	if( fe4 )
	{
		gosJoystick_DestroyEffect(&fe4);
		fe4=0;
	}
	gos_DeleteFont(font3d);
}




void EasyDrawLine( int X0, int Y0, int X1, int Y1, DWORD Color )
{
	gos_VERTEX v[2];

	memset( v,0,sizeof(v) );
	v[0].rhw		= 1.0;
	v[1].rhw		= 1.0;

	v[0].x		= (float)X0;
	v[0].y		= (float)Y0;
	v[0].argb	= Color;

	v[1].x		= (float)X1;
	v[1].y		= (float)Y1;
	v[1].argb	= Color;

	gos_SetRenderState( gos_State_Texture, 0 );
	gos_SetRenderState( gos_State_ZWrite, 0 );
	gos_SetRenderState( gos_State_ZCompare, 0 );
	gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );

	gos_DrawLines( v, 2 );
}				

void LoadEffect(int val)
{
	char tmp[64];
	gosJoystick_DestroyEffect(&fe4);
	sprintf(tmp, "assets\\feedback\\%s", FFEs[val]);
	SPEW(("jreicher","loading '%s'", FFEs[val]));
	gosJoystick_LoadEffect(&fe4, 0, tmp);
}




//
//
//
void __stdcall GetGameOSEnvironment(char* CommandLine)
{
	CommandLine = CommandLine;
	Environment.applicationName			= "Test Input";
	Environment.screenWidth				= 800;
	Environment.screenHeight			= 600;
	Environment.bitDepth				= 16;
	Environment.debugLog				= "";			//"DebugLog.txt";
	Environment.spew					= "";//GameOS_DirectInput";			

	Environment.DoGameLogic				= DoGameLogic;
	Environment.InitializeGameEngine	= InitializeGameEngine;
	Environment.TerminateGameEngine		= TerminateGameEngine;
	Environment.UpdateRenderers			= UpdateDisplay;

	Environment.memoryTraceLevel		= 10;

	Environment.soundChannels			= 0;
	Environment.soundDisable			= true;

	Environment.Texture_A_256			= 8;

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

