#include <GameOS\pch.hpp>
#include <GosScript\GosScriptHeaders.hpp>


#include <string.h>

HGOSAUDIO sample[32];
HGOSFONT3D font3d;
void DrawPie(DWORD color, int x, int y, float size, bool grad);
void DrawRing(DWORD color, int x, int y, float inner, float outer, bool grad);
int _stdcall SetListener(void* instance, int args, void * arg[16] );
int _stdcall SetMinMax(void* instance, int args, void * arg[16] );
int _stdcall DrawSound(void* instance, int args, void * arg[16] );
int _stdcall HandlePlayList(void* instance, int args, void * arg[16] );
																 
int _stdcall Play(void* instance, int args, void * arg[16] );
int _stdcall Quiet(void* instance, int args, void * arg[16] );

float minDistance[16];
float maxDistance[16];

int soundX[16];
int soundY[16];

float mixerX;
float mixerY;
int step = 0;

int selected = 0;

bool musicToggle = false;

unsigned long  fs[7] = {0,0,0,0,0,0};
unsigned char *f[7] = {0,0,0,0,0,0};
HGOSAUDIO playlistResource;

#define EFFECTS 16

HGOSFILE hFile = 0;


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall InitializeGameEngine()
{
    //gosAudio_SetSpeakerConfig( gosAudio_Quadraphonic );

	// load a font to display the various questions
	font3d = gos_LoadFont( "assets\\graphics\\fonttexture.tga");
	gos_TextSetAttributes( font3d, 0xffffffff, -24, true, true, true, false );

	gosAudio_CreateResource(&sample[1],  gosAudio_CachedFile, "Assets\\Sounds\\thunder.wav" );
	gosAudio_CreateResource(&sample[2],  gosAudio_CachedFile, "Assets\\Sounds\\crickets.wav" );
	gosAudio_CreateResource(&sample[3],  gosAudio_CachedFile, "Assets\\Sounds\\fly.wav" );
	gosAudio_CreateResource(&sample[4],  gosAudio_CachedFile, "Assets\\Sounds\\afart.wav" );
	gosAudio_CreateResource(&sample[5],  gosAudio_CachedFile, "Assets\\Sounds\\burn.wav" );
	gosAudio_CreateResource(&sample[6],  gosAudio_CachedFile, "Assets\\Sounds\\cuckoo[2].wav" );
	gosAudio_CreateResource(&sample[7],  gosAudio_CachedFile, "Assets\\Sounds\\dadsays.wav" );
	gosAudio_CreateResource(&sample[8],  gosAudio_CachedFile, "Assets\\Sounds\\rimshot[2].wav" );
	gosAudio_CreateResource(&sample[9],  gosAudio_CachedFile, "Assets\\Sounds\\sfx_helicopter_enginerun.wav" );
	gosAudio_CreateResource(&sample[10], gosAudio_CachedFile, "Assets\\Sounds\\vomit.wav" );
	gosAudio_CreateResource(&sample[11], gosAudio_CachedFile, "Assets\\Sounds\\whistlup[1].wav" );
	gosAudio_CreateResource(&sample[12], gosAudio_CachedFile, "Assets\\Sounds\\sfx_ac_usfire.wav" );
	gosAudio_CreateResource(&sample[13], gosAudio_CachedFile, "Assets\\Sounds\\sfx_cppc_fire.wav" );
	gosAudio_CreateResource(&sample[14], gosAudio_CachedFile, "Assets\\Sounds\\sfx_generic_splashsm.wav" );
	gosAudio_CreateResource(&sample[15], gosAudio_CachedFile, "Assets\\Sounds\\sfx_explo6.wav" );
	gosAudio_CreateResource(&sample[16], gosAudio_CachedFile, "Assets\\Sounds\\missilelaunch01_22.wav" );

	for(int i=0; i < EFFECTS; i++)
	{
		minDistance[i] = 10.0f;
		maxDistance[i] = 500.0f;
		gosAudio_AllocateChannelSliders( i, gosAudio_MinMaxDistance | gosAudio_Position );
		gosAudio_SetChannelSlider(i, gosAudio_MinMaxDistance, minDistance[i], maxDistance[i] );
		gosAudio_AssignResourceToChannel( i, sample[1+i]);
	}

	gosScript_InitializeProcessor();
	gosScript_RegisterCallback("setminmax", SetMinMax, GOSVAR_INT,0, 0);
	gosScript_RegisterCallback("setlistener", SetListener, GOSVAR_INT,0, 0);
	gosScript_RegisterCallback("drawsound", DrawSound, GOSVAR_INT,0, 0);
	gosScript_RegisterCallback("Play", Play, GOSVAR_INT,0, 0);
	gosScript_RegisterCallback("Quiet", Quiet, GOSVAR_INT,0, 0);
	gosScript_RegisterCallback("HandlePlayList", HandlePlayList, GOSVAR_INT,0, 0);
	gosScript_RegisterVariable("mindistance", &minDistance, GOSVAR_FLOAT,16, 0);
	gosScript_RegisterVariable("maxdistance", &maxDistance, GOSVAR_FLOAT,16, 0);
	gosScript_RegisterVariable("soundX", &soundX, GOSVAR_INT,16, 0);
	gosScript_RegisterVariable("soundY", &soundY, GOSVAR_INT,16, 0);

	gosScript_RegisterVariable("mixerX", &mixerX, GOSVAR_FLOAT,0, 0);
	gosScript_RegisterVariable("mixerY", &mixerY, GOSVAR_FLOAT,0, 0);
	gosScript_RegisterVariable("step", &step, GOSVAR_INT,0, 0);
	//
	// Here's an example of doing a playlist.....
	//
	gosAudio_PlayList playlist;
	gos_GetFile("assets\\sounds\\dd1-10.wav", &f[0], &fs[0]);
	gos_GetFile("assets\\sounds\\dd1-11.wav", &f[1], &fs[1]);
	gos_GetFile("assets\\sounds\\dd1-12.wav", &f[2], &fs[2]);
	gos_GetFile("assets\\sounds\\dd1-13.wav", &f[3], &fs[3]);
	gos_GetFile("assets\\sounds\\dd1-14.wav", &f[4], &fs[4]);
	gos_GetFile("assets\\sounds\\dd1-15.wav", &f[5], &fs[5]);


	playlist.m_dwListLength = 6;
	playlist.m_lpSoundData = (DWORD *) f;
	playlist.m_lpDataLength = (DWORD *) fs;
	gosAudio_CreateResource(&playlistResource, gosAudio_UserMemoryPlayList, "Playlist", NULL, &playlist);
	gosAudio_AssignResourceToChannel( 29, playlistResource);



	gosScript_ExecuteScript("assets\\scripts\\interface.script", 0x1000);
}

	float x,y;
	int dx,dy,dw;
	float cx, cz;
	DWORD b;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall DoGameLogic()
{
	for(int i=0; i < EFFECTS; i++)
	{
		gosAudio_SetChannelSlider(i, gosAudio_Position, (float) soundX[i], 0, (float) -soundY[i] );
	}

	gosAudio_ChannelInfo ci;
	gosAudio_GetChannelInfo(31, &ci);

}	

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

	DrawPie(0xff0000ff, float2long(mixerX) + Environment.screenWidth/2, -float2long(mixerY) + Environment.screenHeight/2, minDistance[selected]*2, 0);
	DrawRing(0xff0000ff, float2long(mixerX) + Environment.screenWidth/2, -float2long(mixerY) + Environment.screenHeight/2, minDistance[selected]*2, maxDistance[selected]*2, 1);


	gos_TextSetAttributes( font3d, 0xff00ff00, -24, true, true, true, false );

	gos_TextSetPosition(32,0);
	float fromListener = (float) sqrt( pow(soundX[selected]-mixerX,2) + pow(soundY[selected]-mixerY, 2) );
	gos_TextDraw("Distance outside Attenuation Start: %.0f meters", minDistance[selected] < fromListener ? fromListener - minDistance[selected]  : 0);

	gos_TextSetPosition(32,32);
	gos_TextDraw("Distance from listener: %.0f meters", fromListener );

	gos_TextSetPosition(32,64);
	gos_TextDraw("Atten. Start:");
	gos_TextSetPosition(256,64);
	gos_TextDraw("%.0f m", minDistance[selected] );

	gos_TextSetPosition(32,128);
	gos_TextDraw("Attent End:");
	gos_TextSetPosition(256,128);
	gos_TextDraw("%.0f m", maxDistance[selected] );

	DWORD w,h;
	gos_TextStringLength(&w,&h,"Use left and right arrows keys to rotate listener");
	
	gos_TextSetPosition((Environment.screenWidth/2)-(w/2), 768-64);
	gos_TextDraw("Use left and right arrows keys to rotate listener");
	gos_TextStringLength(&w,&h,"Use up and down arrows keys to step listener forward and back");
	gos_TextSetPosition((Environment.screenWidth/2)-(w/2), 768-32);
	gos_TextDraw("Use up and down arrows keys to step listener forward and back");



}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall TerminateGameEngine()
{
	gosScript_ShutdownProcessor();

	for(int i =1; i < EFFECTS+1; i++)
	{
		gosAudio_DestroyResource(&sample[i]);
		sample[i] = 0;
	}

 	gosAudio_DestroyResource(&playlistResource);

	
	//
	// These playlist resources need to be freed AFTER
	// the playlistResource is destroyed.
	//
	for(i=0; i < 6; i++)
	{
		gos_Free(f[i]);
		f[i] = 0;
	}
	
	
	if (hFile)
		gos_CloseFile(hFile);

	gos_DeleteFont(font3d);
}

void __stdcall GetGameOSEnvironment(char* CommandLine)
{
	CommandLine = CommandLine;
	Environment.applicationName			= "Test Sound";
	Environment.version					= "";
	Environment.screenWidth				= 1024;
	Environment.screenHeight			= 768;
	Environment.fullScreen				= 0;
	Environment.bitDepth				= 16;
	Environment.debugLog				= "";
	Environment.spew					= "GameOS_MemoryVerbose";			
	Environment.memoryTraceLevel		= 5;

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

	Environment.soundDevice				= 0;
	Environment.soundHiFi				= 0;
	Environment.soundChannels			= 32;
	Environment.soundDisable			= false;
    Environment.soundMixInHardware      = false;

	Environment.Texture_A_256			= 8;

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

void DrawPie(DWORD color, int x, int y, float diameter, bool grad)
{
	gos_PushRenderStates();
	gos_SetRenderState( gos_State_Texture, 0 );
	gos_SetRenderState( gos_State_Filter, gos_FilterNone );
	gos_SetRenderState( gos_State_ZCompare, 0 );
	gos_SetRenderState( gos_State_ZWrite, 0 );
	gos_SetRenderState( gos_State_AlphaTest, 0 );
	gos_SetRenderState( gos_State_Perspective, 0 );
	gos_SetRenderState( gos_State_Specular, 0 );
	gos_SetRenderState( gos_State_Dither, 0 );
	gos_SetRenderState( gos_State_Clipping, 2 );
	gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulate );
	gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud );
	gos_SetRenderState( gos_State_MonoEnable, 0 );

	// if we want translucence
	gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );

	gos_VERTEX PieData[17];	
	float SizeOfPie = diameter;

	memset( &PieData[0], 0, sizeof(PieData) );

	PieData[0].x = (float) x;
	PieData[0].y = (float) y;

	PieData[0].rhw=1.0f;
	for( int t1=1; t1<16; t1++ )
	{
		PieData[t1].x=(float)(PieData[0].x+SizeOfPie/2*sin( (2.0f*3.1415926f*(t1-1))/14.0f ));
		PieData[t1].y=(float)(PieData[0].y-SizeOfPie/2*cos( (2.0f*3.1415926f*(t1-1))/14.0f ));
		PieData[t1].rhw=1.0f;
	}
	PieData[t1].x=(float)(PieData[0].x+SizeOfPie/2*sin( 0 ));
	PieData[t1].y=(float)(PieData[0].y-SizeOfPie/2*cos( 0 ));
	PieData[t1].rhw=1.0f;

	PieData[0].argb=color;
	for( t1=1; t1<16; t1++ )
	{
		if (grad)
			PieData[t1].argb=color & 0x00ffffff;
		else
			PieData[t1].argb=color;
	}
	gos_DrawFans( PieData, 16 );

	gos_PopRenderStates();
}

int _stdcall SetMinMax(void* instance, int args, void * arg[16] )
{
	instance; args; arg;
	int id = *((long *)arg[0]);

	if (minDistance[id] <= 0.0f)
		minDistance[id] = 1.0f;

	if (maxDistance[id] <= 0.0f)
		maxDistance[id] = 1.0f;
	if (minDistance[id] == maxDistance[id])
		maxDistance[id] += .01f;

	gosAudio_SetChannelSlider(id, gosAudio_MinMaxDistance, minDistance[id], maxDistance[id] );

	return true;
}

int _stdcall DrawSound(void* instance, int args, void * arg[16] )
{
	instance; args; arg;
	int id = *((long *)arg[0]);
	int selected = *((long *)arg[1]);

	if (selected == id)
		DrawPie(0xff00ff00, soundX[id]+(Environment.screenWidth/2), soundY[id]+(Environment.screenHeight/2),32,1);	  
	else
		DrawPie(0xffff0000, soundX[id]+(Environment.screenWidth/2), soundY[id]+(Environment.screenHeight/2),32,1);	  

	return true;
}


void DrawRing(DWORD color, int x, int y, float inner, float outer, bool grad)
{
	gos_PushRenderStates();
	gos_SetRenderState( gos_State_Texture, 0 );
	gos_SetRenderState( gos_State_Filter, gos_FilterNone );
	gos_SetRenderState( gos_State_ZCompare, 0 );
	gos_SetRenderState( gos_State_ZWrite, 0 );
	gos_SetRenderState( gos_State_AlphaTest, 0 );
	gos_SetRenderState( gos_State_Perspective, 0 );
	gos_SetRenderState( gos_State_Specular, 0 );
	gos_SetRenderState( gos_State_Dither, 0 );
	gos_SetRenderState( gos_State_Clipping, 2 );
	gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulate );
	gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud );
	gos_SetRenderState( gos_State_MonoEnable, 0 );

	// if we want translucence
	gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );

	gos_VERTEX PieData[65];	
	memset( &PieData[0], 0, sizeof(PieData) );


	PieData[0].rhw=1.0f;
	

	float atten = (1000-(outer-inner))/1000;

	if (atten < 0)
		atten = 0;

	DWORD a = (DWORD) atten*255;

	if (a>255)
		a = 255;

	DWORD attenColor = (a << 24);

	float inc = 14.0f;
	for( int t1=0; t1<56; t1+=4 )
	{
		PieData[t1].x=(float)(x+inner/2*sin( (2.0f*3.1415926f*(t1/4))/inc ));
		PieData[t1].y=(float)(y-inner/2*cos( (2.0f*3.1415926f*(t1/4))/inc ));
		PieData[t1].rhw=1.0f;

		PieData[t1+1].x=(float)(x+outer/2*sin( (2.0f*3.1415926f*(t1/4))/inc ));
		PieData[t1+1].y=(float)(y-outer/2*cos( (2.0f*3.1415926f*(t1/4))/inc ));
		PieData[t1+1].rhw=1.0f;

		PieData[t1+2].x=(float)(x+outer/2*sin( (2.0f*3.1415926f*((t1/4)+1))/inc ));
		PieData[t1+2].y=(float)(y-outer/2*cos( (2.0f*3.1415926f*((t1/4)+1))/inc ));
		PieData[t1+2].rhw=1.0f;

		PieData[t1+3].x=(float)(x+inner/2*sin( (2.0f*3.1415926f*((t1/4)+1))/inc ));
		PieData[t1+3].y=(float)(y-inner/2*cos( (2.0f*3.1415926f*((t1/4)+1))/inc ));
		PieData[t1+3].rhw=1.0f;

		PieData[t1].argb =color;
		PieData[t1+3].argb =color;
		if (grad)
		{
			PieData[t1+1].argb=(color & 0xffffff) + attenColor;
			PieData[t1+2].argb=(color & 0xffffff) + attenColor;
		}
		else
		{
			PieData[t1+1].argb=color;
			PieData[t1+2].argb=color;
		}
	}

	gos_DrawQuads( PieData, 56 );

	for( t1=0; t1<56; t1+=4 )
	{
		PieData[t1].x=(float)(x+outer/2*sin( (2.0f*3.1415926f*(t1/4))/inc ));
		PieData[t1].y=(float)(y-outer/2*cos( (2.0f*3.1415926f*(t1/4))/inc ));
		PieData[t1].rhw=1.0f;

		PieData[t1+1].x=(float)(x+2000.0f/2*sin( (2.0f*3.1415926f*(t1/4))/inc ));
		PieData[t1+1].y=(float)(y-2000.0f/2*cos( (2.0f*3.1415926f*(t1/4))/inc ));
		PieData[t1+1].rhw=1.0f;

		PieData[t1+2].x=(float)(x+2000.0f/2*sin( (2.0f*3.1415926f*((t1/4)+1))/inc ));
		PieData[t1+2].y=(float)(y-2000.0f/2*cos( (2.0f*3.1415926f*((t1/4)+1))/inc ));
		PieData[t1+2].rhw=1.0f;

		PieData[t1+3].x=(float)(x+outer/2*sin( (2.0f*3.1415926f*((t1/4)+1))/inc ));
		PieData[t1+3].y=(float)(y-outer/2*cos( (2.0f*3.1415926f*((t1/4)+1))/inc ));
		PieData[t1+3].rhw=1.0f;

		PieData[t1].argb =(color & 0xffffff) + attenColor;
		PieData[t1+3].argb =(color & 0xffffff) + attenColor;
		PieData[t1+1].argb=(color & 0xffffff) + attenColor;
		PieData[t1+2].argb=(color & 0xffffff) + attenColor;
	}

	gos_DrawQuads( PieData, 56 );

	gos_PopRenderStates();
}

int _stdcall SetListener(void* instance, int args, void * arg[16] )
{
	instance; args; arg;
	int rot = *((long *)arg[0]);

	float rot2 = (float) rot;

	rot2 = (rot2/360) * (2.0f*3.1415926f);
	gosAudio_SetChannelSlider(gosAudio_Mixer, gosAudio_FrontOrientation, -sinf(rot2), 0.0f, cosf(rot2) );

	if (step)
	{
		float tmpX = (2*step) *-sinf(rot2);
		float tmpY = (2*step) *cosf(rot2);
		mixerX += tmpX;
		mixerY += tmpY;
		gosAudio_SetChannelSlider(gosAudio_Mixer, gosAudio_Position, (float) mixerX, 0, (float) mixerY );
	}



	return 1;
}


int _stdcall Quiet(void* instance, int args, void * arg[16] )
{
	instance; args; arg;
	int id = *((long *)arg[0]);
	gosAudio_SetChannelPlayMode(id, gosAudio_Stop);
	return 1;
}

int _stdcall Play(void* instance, int args, void * arg[16] )
{
	instance; args; arg;
	selected = *((long *)arg[0]);
	gosAudio_SetChannelPlayMode(selected, gosAudio_Loop); // gosAudio_PlayOnce
	return 1;
}

int _stdcall HandlePlayList(void* instance, int args, void * arg[16] )
{
	instance; args; arg;
	int state = (int) (arg[0]);
	switch(state)
	{
	case 0:
		gosAudio_SetChannelPlayMode(29,gosAudio_Stop);
		break;
	case 1:
		gosAudio_SetChannelPlayMode(29,gosAudio_Loop);
		break;
	case 2:
		gosAudio_SetChannelPlayMode(29,gosAudio_Pause);
		break;
	case 3:
		gosAudio_SetChannelPlayMode(29,gosAudio_Continue);
		break;
	}


	return 1;
}										 
