//interfaceoptions.cpp
//user interface for setting game options

#include <OpenGL/gl.h>
#include "gametime.h"
#include <string.h>
#include <stdio.h>
#include "interfaceutil.h"
#include "gamemem.h"
#include "fileio.h"
#include "screen.h"
#include "controls.h"
#include "text.h"
#include "interface.h"
#include "gameinitexit.h"
#include "parser.h"
#include "writeout.h"
#include "textures.h"
#include "config.h"
#include "gamesound.h"
#include "textures.h"
#include "renderframe.h"
#include "music.h"

#define kNumControlOptions 14

void InterfaceControlOptions()
{
	int controlOptions[kNumControlOptions]={kInputGasButton,kInputBrakeButton,kInputSteerLeftButton,kInputSteerRightButton,kInputHandbrakeButton,kInputKickdownButton,kInputCamera,kInputCameraReverse,kInputCameraChangeCar,kInputPause,kInputGearUp,kInputGearDown,kInputHorn,kInputChat};

	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,kNumControlOptions+1,"Controls");

	strcpy(menu.items[kNumControlOptions].label,"Return to previous menu");
	menu.items[kNumControlOptions-1].lineSpacing*=1.5;
	menu.background=FileGetReference("background-options.tif");
	menu.RenderCallback=InterfaceRenderReplay;
	menu.itemsYPos+=0.1;
	
	char itemStrings[kNumControlOptions][32]={"Accelerate","Brake","Steer Left","Steer Right","Handbrake","Full Throttle","Change Camera","Look Backwards","Replay Car View","Pause Game","Shift Up","Shift Down","Horn","Type Message"};
	for(int i=0;i<kNumControlOptions;i++)
	{
		menu.items[i].size*=0.7;
		menu.items[i].lineSpacing*=0.6;
	}
		
	int exit=false;
	do{
		for(int i=0;i<kNumControlOptions;i++)
		{
			int keyUsed=false;
			int controllerUsed=false;
			for(int j=0;j<=kInputITunesPlay;j++)
				if(gConfig->keys[controlOptions[i]].keyID==gConfig->keys[j].keyID&&j!=controlOptions[i])
					keyUsed=true;
			for(int j=0;j<=kInputITunesPlay;j++)
				if(gConfig->keys[controlOptions[i]].controllerID1==gConfig->keys[j].controllerID1
					&&gConfig->keys[controlOptions[i]].controllerID2==gConfig->keys[j].controllerID2
					&&gConfig->keys[controlOptions[i]].elementID==gConfig->keys[j].elementID
					&&j!=controlOptions[i])
					controllerUsed=true;					
			if(gConfig->keys[controlOptions[i]].controllerID1)
			{
				if(keyUsed&&controllerUsed)
					sprintf(menu.items[i].label,"%s:\255#r\255\t%s\t%s",itemStrings[i],gConfig->keys[controlOptions[i]].identifier,gConfig->keys[controlOptions[i]].controllerIdentifier);		
				else if(keyUsed)
					sprintf(menu.items[i].label,"%s:\255#r\255\t%s\t\255#a\255%s",itemStrings[i],gConfig->keys[controlOptions[i]].identifier,gConfig->keys[controlOptions[i]].controllerIdentifier);		
				else if(controllerUsed)
					sprintf(menu.items[i].label,"%s:\255#a\255\t%s\t\255#r\255%s",itemStrings[i],gConfig->keys[controlOptions[i]].identifier,gConfig->keys[controlOptions[i]].controllerIdentifier);		
				else
					sprintf(menu.items[i].label,"%s:\255#a\255\t%s\t%s",itemStrings[i],gConfig->keys[controlOptions[i]].identifier,gConfig->keys[controlOptions[i]].controllerIdentifier);		
			}
			else if(keyUsed)
				sprintf(menu.items[i].label,"%s:\255#r\255\t%s",itemStrings[i],gConfig->keys[controlOptions[i]].identifier);		
			else
				sprintf(menu.items[i].label,"%s:\255#a\255\t%s",itemStrings[i],gConfig->keys[controlOptions[i]].identifier);		
		}			
		InterfaceMenuZoomAnimation(&menu,-1,true);
		int sel=InterfaceGetUserMenuSelection(&menu);
		if(sel!=kInterfaceMenuEsc&&sel<kNumControlOptions)
		{
			while(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter));

			menu.initialSelection=sel;
			char keyString[80];
			sprintf(keyString,"Press the new Key or Button for '%s'\n (Or press delete to clear)",itemStrings[sel]);
			InterfaceDrawStrings("Assign new Key",keyString,kFileErr);

			GetInput(gConfig->keys+controlOptions[sel]);
			
			int interfaceKeyPressed;
			do{
				interfaceKeyPressed=false;
				for(int i=kInterfaceKeyUp;i<kInterfaceNumKeys;i++)
					if(GetInterfaceKey(i))
						interfaceKeyPressed=true;
				if(GetButtonInput(kInputITunesNext)||GetButtonInput(kInputITunesPlay))
					interfaceKeyPressed=true;
			}while(interfaceKeyPressed);
		} 
		else
			exit=true;
		
	}while(!exit);

	InterfaceDisposeMenu(&menu);
}

#define kNumTauntOptions 10
void InterfaceTauntOptions()
{
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,kNumTauntOptions+1,"Taunts");

	strcpy(menu.items[kNumTauntOptions].label,"Return to previous menu");
	menu.items[kNumTauntOptions-1].lineSpacing*=1.5;
	menu.background=FileGetReference("background-options.tif");
	menu.RenderCallback=InterfaceRenderReplay;
	
	char itemStrings[5][32];
	for(int i=0;i<kNumTauntOptions;i++)
	{
		menu.items[i].size*=0.75;
		if(i%2)
		{
			menu.items[i].lineSpacing*=0.9;
			menu.items[i].flags|=kInterfaceMenuItemTypeable;
			strcpy(menu.items[i].type,gConfig->taunts[i/2]);
			sprintf(menu.items[i].label,"Taunt %d message: ",i/2+1);
		}
		else
		{
			menu.items[i].lineSpacing*=0.65;
			sprintf(itemStrings[i/2],"Taunt %d key",i/2+1);
		}
	}
		
	int exit=false;
	do{
		for(int i=0;i<kNumTauntOptions;i++)
			if(!(i%2))
			{
				int keyUsed=false;
				int controllerUsed=false;
				for(int j=0;j<=kInputITunesPlay;j++)
					if(gConfig->keys[kInputTaunt1+i/2].keyID==gConfig->keys[j].keyID&&j!=kInputTaunt1+i/2)
						keyUsed=true;
				for(int j=0;j<=kInputITunesPlay;j++)
					if(gConfig->keys[kInputTaunt1+i/2].controllerID1==gConfig->keys[j].controllerID1
						&&gConfig->keys[kInputTaunt1+i/2].controllerID2==gConfig->keys[j].controllerID2
						&&gConfig->keys[kInputTaunt1+i/2].elementID==gConfig->keys[j].elementID
						&&j!=kInputTaunt1+i/2)
						controllerUsed=true;					
				if(gConfig->keys[kInputTaunt1+i/2].controllerID1)
				{
					if(keyUsed&&controllerUsed)
						sprintf(menu.items[i].label,"%s:\255#r\255\t%s\t%s",itemStrings[i/2],gConfig->keys[kInputTaunt1+i/2].identifier,gConfig->keys[kInputTaunt1+i/2].controllerIdentifier);		
					else if(keyUsed)
						sprintf(menu.items[i].label,"%s:\255#r\255\t%s\t\255#a\255%s",itemStrings[i/2],gConfig->keys[kInputTaunt1+i/2].identifier,gConfig->keys[kInputTaunt1+i/2].controllerIdentifier);		
					else if(controllerUsed)
						sprintf(menu.items[i].label,"%s:\255#a\255\t%s\t\255#r\255%s",itemStrings[i/2],gConfig->keys[kInputTaunt1+i/2].identifier,gConfig->keys[kInputTaunt1+i/2].controllerIdentifier);		
					else
						sprintf(menu.items[i].label,"%s:\255#a\255\t%s\t%s",itemStrings[i/2],gConfig->keys[kInputTaunt1+i/2].identifier,gConfig->keys[kInputTaunt1+i/2].controllerIdentifier);		
				}
				else if(keyUsed)
					sprintf(menu.items[i].label,"%s:\255#r\255\t%s",itemStrings[i/2],gConfig->keys[kInputTaunt1+i/2].identifier);		
				else
					sprintf(menu.items[i].label,"%s:\255#a\255\t%s",itemStrings[i/2],gConfig->keys[kInputTaunt1+i/2].identifier);		
			}
					
		InterfaceMenuZoomAnimation(&menu,-1,true);
		int sel=InterfaceGetUserMenuSelection(&menu);
		if(sel!=kInterfaceMenuEsc&&sel<kNumTauntOptions&&!(sel%2))
		{
			while(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter));

			menu.initialSelection=sel;
			char keyString[80];
			sprintf(keyString,"Press the new Key or Button for '%s'",itemStrings[sel/2]);
			InterfaceDrawStrings("Assign new Key",keyString,kFileErr);

			GetInput(gConfig->keys+kInputTaunt1+sel/2);
			
			int interfaceKeyPressed;
			do{
				interfaceKeyPressed=false;
				for(int i=kInterfaceKeyUp;i<kInterfaceNumKeys;i++)
					if(GetInterfaceKey(i))
						interfaceKeyPressed=true;
			}while(interfaceKeyPressed);
		} 
		else
			exit=true;
		
	}while(!exit);

	for(int i=1;i<kNumTauntOptions;i+=2)
		strcpy(gConfig->taunts[i/2],menu.items[i].type);

	InterfaceDisposeMenu(&menu);
}

void InterfaceCalibrateAxis()
{
	if(gConfig->axis[kInputSteerAxis].axisControllerID1>0)
	{
		InterfaceDrawStrings("Calibrate Axis","Move the Steering Axis to its left and right \nmaximum several times and hit Return.",kFileErr);
		CalibrateAxis(kInputSteerAxis);
	}
	if(!gConfig->seperateGasBrake)
		if(gConfig->axis[kInputThrottleBrakeAxis].axisControllerID1>0)
		{
			InterfaceDrawStrings("Calibrate Axis","Move the Gas/Brake Axis to its left and right \nmaximum several times and hit Return.",kFileErr);
			CalibrateAxis(kInputThrottleBrakeAxis);
		}
	FlushKeys();
}

enum{
	kAnalougeSteerAxis,
	kAnalougeGasSeperateAxes,
	kAnalougeInvertGas,
	kAnalougeGasAxis,
	kAnalougeBrakeAxis,
	kAnalougeDisableTCS,
	kAnalougeCalibrate,
	kAnalougeSteerCenterTolerance,
	kAnalougeGasCenterTolerance,
	kAnalougeFFB,
	kAnalougeFFBIntensity,
	kAnalougeExit,
	kAnalougeNumOptions
};

void InterfaceAnalogueControlOptions()
{
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,kAnalougeNumOptions,"Analog Controls");
	menu.background=FileGetReference("background-options.tif");
	menu.RenderCallback=InterfaceRenderReplay;

	
	char itemStrings[][32]={"Steering","Seperate Gas/Brake:","Invert Gas/Brake axes","Gas","Brake","Traction Assistance","Calibrate Axis...","Steering Tolerance:","Gas Tolerance:","","FFB Intensity:","Return to previous menu"};

	for(int i=0;i<kAnalougeNumOptions;i++)
		sprintf(menu.items[i].label,"%s",itemStrings[i]);		
	
	menu.items[kAnalougeFFB].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kAnalougeInvertGas].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kAnalougeGasSeperateAxes].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kAnalougeDisableTCS].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kAnalougeFFBIntensity].flags|=kInterfaceMenuItemArrowInput|kInterfaceMenuItemSlider;
	menu.items[kAnalougeSteerCenterTolerance].flags|=kInterfaceMenuItemArrowInput|kInterfaceMenuItemSlider;
	menu.items[kAnalougeGasCenterTolerance].flags|=kInterfaceMenuItemArrowInput|kInterfaceMenuItemSlider;
	if(!gFFB)
	{
		menu.items[kAnalougeFFB].flags|=kInterfaceMenuItemDisabled;
		menu.items[kAnalougeFFBIntensity].flags|=kInterfaceMenuItemDisabled;
	}
	if(!gInputHID)
		menu.items[kAnalougeCalibrate].flags|=kInterfaceMenuItemDisabled;
	menu.items[kAnalougeExit-1].lineSpacing*=1.5;

	for(int i=0;i<kAnalougeExit;i++)
	{
		menu.items[i].size*=0.75;
		menu.items[i].lineSpacing*=0.75;
	}

	int exit=false;
	do{
		if(gConfig->axis[kInputSteerAxis].axisControllerID1)
			sprintf(menu.items[kAnalougeSteerAxis].label,"%s: \255#a\255%s",itemStrings[kAnalougeSteerAxis],gConfig->axis[kInputSteerAxis].axisIdentifier);		
		else
			sprintf(menu.items[kAnalougeSteerAxis].label,"%s: \255#a\255not assigned",itemStrings[kAnalougeSteerAxis]);		
		if(gConfig->seperateGasBrake)
		{
			if(gConfig->axis[kInputThrottleAxis].axisControllerID1)
				sprintf(menu.items[kAnalougeGasAxis].label,"%s: \255#a\255%s","Gas",gConfig->axis[kInputThrottleAxis].axisIdentifier);		
			else
				sprintf(menu.items[kAnalougeGasAxis].label,"%s: \255#a\255not assigned","Gas");		
			if(gConfig->axis[kInputBrakeAxis].axisControllerID1)
				sprintf(menu.items[kAnalougeBrakeAxis].label,"%s: \255#a\255%s","Brake",gConfig->axis[kInputBrakeAxis].axisIdentifier);		
			else
				sprintf(menu.items[kAnalougeBrakeAxis].label,"%s: \255#a\255not assigned","Brake");		
		} else {
			if(gConfig->axis[kInputThrottleBrakeAxis].axisControllerID1)
				sprintf(menu.items[kAnalougeGasAxis].label,"%s: \255#a\255%s","Gas/Brake",gConfig->axis[kInputThrottleBrakeAxis].axisIdentifier);		
			else
				sprintf(menu.items[kAnalougeGasAxis].label,"%s: \255#a\255not assigned","Gas/Brake");		
			sprintf(menu.items[kAnalougeBrakeAxis].label,"%s: \255#a\255not applicable","Brake");		
		}
				
		sprintf(menu.items[kAnalougeFFB].label,"Force Feedback: \255#a\255%s",gConfig->ffb?"On":"Off");
		sprintf(menu.items[kAnalougeInvertGas].label,"Invert Gas/Brake axes: \255#a\255%s",gConfig->reverseGas?"On":"Off");
		sprintf(menu.items[kAnalougeDisableTCS].label,"Traction Assistance: \255#a\255%s",gConfig->disableAnalogueTCS?"Off":"On");
		sprintf(menu.items[kAnalougeGasSeperateAxes].label,"Seperate Gas/Brake: \255#a\255%s",gConfig->seperateGasBrake?"On":"Off");
		if(gConfig->seperateGasBrake)
			menu.items[kAnalougeBrakeAxis].flags&=~kInterfaceMenuItemDisabled;
		else
			menu.items[kAnalougeBrakeAxis].flags|=kInterfaceMenuItemDisabled;			

		menu.items[kAnalougeFFBIntensity].sliderPos=gConfig->ffbIntensity;
		menu.items[kAnalougeSteerCenterTolerance].sliderPos=gConfig->axis[0].deadzone*5.0;
		menu.items[kAnalougeGasCenterTolerance].sliderPos=gConfig->axis[1].deadzone*5.0;
		
		if(gInputHID&&(gConfig->axis[kInputThrottleBrakeAxis].axisControllerID1||gConfig->axis[kInputSteerAxis].axisControllerID1))
			menu.items[kAnalougeCalibrate].flags&=~kInterfaceMenuItemDisabled;
		else
			menu.items[kAnalougeCalibrate].flags|=kInterfaceMenuItemDisabled;			

		int sel=InterfaceGetUserMenuSelection(&menu);
		menu.initialSelection=sel&kInterfaceMenuItemMask;
		switch(menu.initialSelection)
		{
			case kAnalougeSteerAxis:
			case kAnalougeGasAxis:
			case kAnalougeBrakeAxis:
				while(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter));

				menu.initialSelection=sel;
				char keyString[80];
				switch(menu.initialSelection)
				{
					case kAnalougeSteerAxis:
						sprintf(keyString,"Move the new axis for '%s'","Steering");
						InterfaceDrawStrings("Assign new Axis",keyString,kFileErr);
						GetAxis(gConfig->axis+kInputSteerAxis,false);
						break;
					case kAnalougeGasAxis:
						if(!gConfig->seperateGasBrake)
						{
							sprintf(keyString,"Move the new axis for '%s'","Gas/Brake");
							InterfaceDrawStrings("Assign new Axis",keyString,kFileErr);
							GetAxis(gConfig->axis+kInputThrottleBrakeAxis,false);
						}
						else
						{
							sprintf(keyString,"Move the new axis for '%s'","Gas");
							InterfaceDrawStrings("Assign new Axis",keyString,kFileErr);
							GetAxis(gConfig->axis+kInputThrottleAxis,true);
						}
						break;
					case kAnalougeBrakeAxis:
						sprintf(keyString,"Move the new axis for '%s'","Brake");
						InterfaceDrawStrings("Assign new Axis",keyString,kFileErr);
						GetAxis(gConfig->axis+kInputBrakeAxis,true);
						break;
				}
				InterfaceMenuZoomAnimation(&menu,-1,true);
				
				break;
			case kAnalougeGasSeperateAxes:
				gConfig->seperateGasBrake=!gConfig->seperateGasBrake;
				break;
			case kAnalougeInvertGas:
				gConfig->reverseGas=!gConfig->reverseGas;
				break;
			case kAnalougeCalibrate:
				InterfaceCalibrateAxis();
				InterfaceMenuZoomAnimation(&menu,-1,true);
				break;
			case kAnalougeFFB:
				gConfig->ffb=!gConfig->ffb;
				break;
			case kAnalougeDisableTCS:
				gConfig->disableAnalogueTCS=!gConfig->disableAnalogueTCS;
				break;
			case kAnalougeFFBIntensity:
				if(sel&kInterfaceMenuLeftArrow){
					gConfig->ffbIntensity-=0.05;
					if(gConfig->ffbIntensity<0)gConfig->ffbIntensity=0;
				}
				else{
					gConfig->ffbIntensity+=0.05;
					if(gConfig->ffbIntensity>1.0)gConfig->ffbIntensity=1.0;
				}
				break;
			case kAnalougeSteerCenterTolerance:
				if(sel&kInterfaceMenuLeftArrow){
					gConfig->axis[0].deadzone-=0.01;
					if(gConfig->axis[0].deadzone<0)gConfig->axis[0].deadzone=0;
				}
				else{
					gConfig->axis[0].deadzone+=0.01;
					if(gConfig->axis[0].deadzone>0.2)gConfig->axis[0].deadzone=0.2;
				}
				break;
			case kAnalougeGasCenterTolerance:
				if(sel&kInterfaceMenuLeftArrow){
					gConfig->axis[1].deadzone-=0.01;
					if(gConfig->axis[1].deadzone<0)gConfig->axis[1].deadzone=0;
				}
				else{
					gConfig->axis[1].deadzone+=0.01;
					if(gConfig->axis[1].deadzone>0.2)gConfig->axis[1].deadzone=0.2;
				}
				break;
			default: 
				exit=true;
		}
	}while(!exit);
	gConfig->axis[2].deadzone=gConfig->axis[1].deadzone;
	gConfig->axis[3].deadzone=gConfig->axis[1].deadzone;
	InterfaceDisposeMenu(&menu);
}

enum{
	kVideoOptionScreenSize,
	kVideoOptionFullscreen,
	kVideoOptionShadows,
	kVideoOptionTextureFilter,
	kVideoOptionTextureQuality,
//	kVideoOptionClipDistance,
	kVideoOptionInteriorDisplay,
	kVideoOptionColor32Bit,
	kVideoOptionFSAA,
	kVideoOptionMotionBlur,
	kVideoOptionsShowReplays,
	//kVideoOptionsFPS,
	kVideoOptionReturn,
	kNumVideoOptions
};

#define kMaxTextureQuality 9
#define kMinTextureQuality 0

void InterfaceVideoOptions()
{
	int screenReInitRequired=false;
	int textureReLoadRequired=false;
	int glReInitRequired=false;
	
	int videoMode=0;
	for(int i=0;i<gVideoNumModes;i++)
		if(gConfig->screenXSize==gVideoModes[i].width&&gConfig->screenYSize==gVideoModes[i].height)
			videoMode=i;

	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,kNumVideoOptions,"Video Options");
	menu.background=FileGetReference("background-options.tif");
	menu.RenderCallback=InterfaceRenderReplay;

	char itemStrings[][256]={"Set the display resolution for Redline to use. Larger values means sharper graphics, but may slow the game down.",
		"Switch between fullscreen and windowed modes. You can also switch at any time by pressing Command-F.",
		"Turn shadows and light cones on or off. If you can't get Redline to run smooth on your machine, try disabling shadows.",
		"Changes texture filter. Anisotropic filtering results in the smoothest graphics, Bilinear filtering is the fastest.",
		"Changes the texture quality. Higher quality means sharper graphics, but may cause the game to run too slow, if your graphics card doesn't have enough memory.",
//		"Changes the visible display range. Higher values let you see farther, but will cause the game to run slower.",
		"Turns car interor display on or off. Turning interior display off will let the game run faster.",
		"Changes between 16-bit and 32-bit color modes. 32-bit looks much nicer, but may be slower on older graphics cards.",
		"Turns on Full screen Anti-Aliasing. Will cause the game to look smoother, but may cause slowdowns.",
		"Turns motion blur on or off (Arcade modes only). Enabling this may cause severe slowdowns on older hardware.",
		"Play replays of Races behind the menu screens. May slow down menu responsiveness on older systems.",
	//	"Display a frames-per-second counter in your HUD, to indicate how fast the graphics are rendering.",
		""
		};
	for(int i=0;i<menu.numItems;i++)
		strcpy(menu.items[i].describtion,itemStrings[i]);


	strcpy(menu.items[kVideoOptionReturn].label,"Return to previous menu");
	menu.items[kVideoOptionReturn-1].lineSpacing*=1.5;
	
	for(int i=kVideoOptionScreenSize;i<=kVideoOptionsShowReplays;i++)
		menu.items[i].flags|=kInterfaceMenuItemArrowInput;

//	menu.items[kVideoOptionClipDistance].flags|=kInterfaceMenuItemSlider;
//	strcpy(menu.items[kVideoOptionClipDistance].label,"Clipping Distance:");
	menu.items[kVideoOptionTextureQuality].flags|=kInterfaceMenuItemSlider;
	strcpy(menu.items[kVideoOptionTextureQuality].label,"Texture Quality:");
	menu.enterAlwaysOK=true;
	for(int i=0;i<kVideoOptionReturn;i++)
	{
		menu.items[i].size*=0.75;
		menu.items[i].lineSpacing*=0.75;
	}

	if(gConfig->textureQuality<kMinTextureQuality)
		gConfig->textureQuality=kMinTextureQuality;
	if(gConfig->textureQuality>kMaxTextureQuality)
		gConfig->textureQuality=kMaxTextureQuality;
			
	if(ScreenNoWindow())
		menu.items[kVideoOptionFullscreen].flags|=kInterfaceMenuItemDisabled;
		
	int exit=false;
	int zoom=false;
	do{
		sprintf(menu.items[kVideoOptionScreenSize].label,"Screen Size: \255#a\255%dx%d",gVideoModes[videoMode].width,gVideoModes[videoMode].height);
		sprintf(menu.items[kVideoOptionFullscreen].label,"Screen Mode: \255#a\255%s",gConfig->fullscreen?"Fullscreen":"Window");
		switch(gConfig->textureFilter){
			case 0: strcpy(menu.items[kVideoOptionTextureFilter].label,"Texture Filter: \255#a\255Bilinear");break;
			case 1: strcpy(menu.items[kVideoOptionTextureFilter].label,"Texture Filter: \255#a\255Trilinear");break;
			case 2: strcpy(menu.items[kVideoOptionTextureFilter].label,"Texture Filter: \255#a\255Anisotropic");break;
		}
		switch(gConfig->fsaa){
			case 0: strcpy(menu.items[kVideoOptionFSAA].label,"Anti-Aliasing: \255#a\255Off");break;
			case 2: strcpy(menu.items[kVideoOptionFSAA].label,"Anti-Aliasing: \255#a\255Medium");break;
			case 4: strcpy(menu.items[kVideoOptionFSAA].label,"Anti-Aliasing: \255#a\255Full");break;
		}
		sprintf(menu.items[kVideoOptionShadows].label,"Shadows & Lighting: \255#a\255%s",gConfig->stencil?"On":"Off");
		sprintf(menu.items[kVideoOptionMotionBlur].label,"Motion Blur: \255#a\255%s",gConfig->motionBlur?"On":"Off");
		sprintf(menu.items[kVideoOptionInteriorDisplay].label,"Interior Display: \255#a\255%s",gConfig->interiorDisplay?"On":"Off");

//		menu.items[kVideoOptionClipDistance].sliderPos=(gConfig->clipFarDistance-160)/640.0;
		menu.items[kVideoOptionTextureQuality].sliderPos=1-((float)gConfig->textureQuality-kMinTextureQuality)/(kMaxTextureQuality-kMinTextureQuality);
		sprintf(menu.items[kVideoOptionColor32Bit].label,"Color Depth: \255#a\255%d",gConfig->color32Bit?32:16);
		sprintf(menu.items[kVideoOptionsShowReplays].label,"Play Background Replays: \255#a\255%s",gConfig->showReplays?"On":"Off");
//		sprintf(menu.items[kVideoOptionsFPS].label,"Show FPS counter: \255#a\255%s",gConfig->performanceStats?"On":"Off");

		if(!zoom){
			InterfaceMenuZoomAnimation(&menu,-1,true);
			zoom=true;
		}

		int sel=InterfaceGetUserMenuSelection(&menu);
		switch(menu.initialSelection=(sel&kInterfaceMenuItemMask))
		{
			case kVideoOptionScreenSize:
				if(sel&kInterfaceMenuLeftArrow)
					videoMode=(videoMode+1)%gVideoNumModes;
				else{
					videoMode--;
					if(videoMode<0)videoMode=gVideoNumModes-1;
				}
				screenReInitRequired=true;
				break;
			case kVideoOptionFullscreen:
				gConfig->fullscreen=!gConfig->fullscreen;
				screenReInitRequired=true;
				break;
			case kVideoOptionShadows:
				gConfig->stencil=!gConfig->stencil;
				break;
			case kVideoOptionMotionBlur:
				gConfig->motionBlur=!gConfig->motionBlur;
				break;
			case kVideoOptionTextureQuality:
				if(!(sel&kInterfaceMenuLeftArrow)){
					if(gConfig->textureQuality>kMinTextureQuality)
						gConfig->textureQuality--;
				}
				else{
					if(gConfig->textureQuality<kMaxTextureQuality)
						gConfig->textureQuality++;
				}
				textureReLoadRequired=true;
				break;
			case kVideoOptionTextureFilter:
				if(!(sel&kInterfaceMenuLeftArrow)){
					gConfig->textureFilter++;
					if(gConfig->textureFilter>(ScreenSupportsAnisotropicFiltering()?2:1))
						gConfig->textureFilter=0;
				}				
				else{
					gConfig->textureFilter--;
					if(gConfig->textureFilter<0)
						gConfig->textureFilter=ScreenSupportsAnisotropicFiltering()?2:1;
				}
				textureReLoadRequired=true;
				break;
/*			case kVideoOptionClipDistance:
				if(sel&kInterfaceMenuLeftArrow){
					if(gConfig->clipFarDistance>160)
					gConfig->clipFarDistance-=20;
				}
				else{
					if(gConfig->clipFarDistance<800)
					gConfig->clipFarDistance+=20;
				}
				glReInitRequired=true;
				break;*/
			case kVideoOptionInteriorDisplay:
				gConfig->interiorDisplay=!gConfig->interiorDisplay;
				break;
			case kVideoOptionColor32Bit:
				gConfig->color32Bit=!gConfig->color32Bit;
				screenReInitRequired=true;
				textureReLoadRequired=true;
				break;
			case kVideoOptionFSAA:
				if(sel&kInterfaceMenuLeftArrow){
					gConfig->fsaa-=2;
					if(gConfig->fsaa<0)gConfig->fsaa=4;
				}
				else
					gConfig->fsaa=(gConfig->fsaa+2)%6;	
					screenReInitRequired=true;			
				break;
			case kVideoOptionsShowReplays:
				gConfig->showReplays=!gConfig->showReplays;
				break;
			
		//	case kVideoOptionsFPS:
		//		gConfig->performanceStats=!gConfig->performanceStats;
		//		break;

			case kVideoOptionReturn:
			case kInterfaceMenuEsc:
			case kInterfaceMenuOK:
				exit=true;
				break;
		}
	}while(!exit);
	
	gConfig->screenXSize=gVideoModes[videoMode].width;
	gConfig->screenYSize=gVideoModes[videoMode].height;
	
	if(textureReLoadRequired)
		TexturesUnloadAll();
	if(screenReInitRequired)
		ScreenReInit();
	else
	{
		if(glReInitRequired)
			InitGL();
	}
	InterfaceDisposeMenu(&menu);
}

enum{
	kGameplayOptionsMetric,
	kGameplayOptionsAutomatic,
	kGameplayOptionsCamera,
	kGameplayOptionsTransparency,
	kGameplayOptionsName,
	kGameplayOptionsRegisterLapTimes,
	kGameplayOptionsShowPlayerNames,
	kGameplayOptionsCornerGuides,
	kGameplayOptionsHugeGames,
	kGameplayOptionsGhost,
	kGameplayOptionsReturn,
	kNumGameplayOptionsButtons
};

void InterfaceGameplayOptions()
{
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,kNumGameplayOptionsButtons,"Gameplay Options");

	char itemStrings[][256]={"Switches the game to use either metric or imperial units for speed, power, mass, etc.",
		"Switches between automatic or manual gear switching.",
		"Switches the default camera mode.",
		"Changes the transparency of in-game displays.",
		"Lets you change your name used in network games and the internet track records.",
		"If you enable this option, your lap times in Time Trial and Challenge modes will be submitted to the internet track record database.",
		"If you enable this, player names will be displayed above the cars in network games.",
		"Show guiding signs informing you about upcoming corners.",
		"Allow races with up to 12 cars. \255#r\255A fast computer and a fast network connection (for multiplayer) are needed for a good gaming experience.",
		"Show a ghost car in Time Trial mode, indicating your best lap.",
		""
		};
	for(int i=0;i<menu.numItems;i++)
		strcpy(menu.items[i].describtion,itemStrings[i]);

	strcpy(menu.items[kGameplayOptionsReturn].label,"Return to previous menu");
	menu.items[kGameplayOptionsReturn-1].lineSpacing*=1.5;
	
	menu.items[kGameplayOptionsMetric].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kGameplayOptionsAutomatic].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kGameplayOptionsCamera].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kGameplayOptionsRegisterLapTimes].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kGameplayOptionsShowPlayerNames].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kGameplayOptionsCornerGuides].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kGameplayOptionsHugeGames].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kGameplayOptionsGhost].flags|=kInterfaceMenuItemArrowInput;
	menu.items[kGameplayOptionsTransparency].flags|=kInterfaceMenuItemArrowInput|kInterfaceMenuItemSlider;
	strcpy(menu.items[kGameplayOptionsTransparency].label,"HUD Transparency:");
	menu.items[kGameplayOptionsName].flags|=kInterfaceMenuItemTypeable;
	menu.items[kGameplayOptionsName].maxTypeLength=kMaxNameLength-1;
	
	strcpy(menu.items[kGameplayOptionsName].label,"Network Name: ");
	strcpy(menu.items[kGameplayOptionsName].type,gConfig->playerName);

	menu.background=FileGetReference("background-options.tif");
	menu.RenderCallback=InterfaceRenderReplay;

	menu.enterAlwaysOK=true;
	
	for(int i=0;i<kGameplayOptionsReturn;i++)
	{
		menu.items[i].size*=0.75;
		menu.items[i].lineSpacing*=0.75;
	}

	int exit=false;
	int zoom=false;
	do{
		sprintf(menu.items[kGameplayOptionsMetric].label,"Units: \255#a\255%s",gConfig->metricUnits?"Metric":"Imperial");
		sprintf(menu.items[kGameplayOptionsAutomatic].label,"Transmission: \255#a\255%s",gConfig->automatic?"Automatic":"Manual");
		sprintf(menu.items[kGameplayOptionsRegisterLapTimes].label,"Internet Lap Time Registering: \255#a\255%s",gConfig->registerLapTimes?"On":"Off");
		sprintf(menu.items[kGameplayOptionsCornerGuides].label,"Show Corner Guides: \255#a\255%s",gConfig->guideSigns?"On":"Off");
		sprintf(menu.items[kGameplayOptionsHugeGames].label,"Allow big races: \255#a\255%s",gConfig->allowHugeGames?"On":"Off");
		sprintf(menu.items[kGameplayOptionsGhost].label,"Show ghost car: \255#a\255%s",!gConfig->noGhost?"On":"Off");
		sprintf(menu.items[kGameplayOptionsShowPlayerNames].label,"Show Network Player Names: \255#a\255%s",gConfig->showPlayerNames?"On":"Off");
		switch(gConfig->cameraMode)
		{
			case kCameraChase:
				sprintf(menu.items[kGameplayOptionsCamera].label,"Default Camera: \255#a\255Chase");break;
			case kCameraChaseClose:
				sprintf(menu.items[kGameplayOptionsCamera].label,"Default Camera: \255#a\255Close Chase");break;
			case kCameraCockpit:
				sprintf(menu.items[kGameplayOptionsCamera].label,"Default Camera: \255#a\255Cockpit");break;
			case kCameraCockpitCarHidden:
				sprintf(menu.items[kGameplayOptionsCamera].label,"Default Camera: \255#a\255Cockpit");break;
		}
		menu.items[kGameplayOptionsTransparency].sliderPos=gConfig->hudTransparency*1/0.8;
		menu.items[kGameplayOptionsTransparency].sliderTransparency=gConfig->hudTransparency;
		
		if(!zoom){
			InterfaceMenuZoomAnimation(&menu,-1,true);
			zoom=true;
		}

		int sel=InterfaceGetUserMenuSelection(&menu);
		switch(menu.initialSelection=(sel&kInterfaceMenuItemMask))
		{
			case kGameplayOptionsGhost:
				gConfig->noGhost=!gConfig->noGhost;
				break;

			case kGameplayOptionsHugeGames:
				gConfig->allowHugeGames=!gConfig->allowHugeGames;
				break;

			case kGameplayOptionsMetric:
				gConfig->metricUnits=!gConfig->metricUnits;
				break;

			case kGameplayOptionsRegisterLapTimes:
				gConfig->registerLapTimes=!gConfig->registerLapTimes;
				break;

			case kGameplayOptionsCornerGuides:
				gConfig->guideSigns=!gConfig->guideSigns;
				break;

			case kGameplayOptionsAutomatic:
				gConfig->automatic=!gConfig->automatic;
				break;
				
			case kGameplayOptionsCamera:
				if(sel&kInterfaceMenuLeftArrow){
					gConfig->cameraMode--;
					if(gConfig->cameraMode<kCameraChase)gConfig->cameraMode=kCameraCockpitCarHidden;
				}
				else{
					gConfig->cameraMode++;
					if(gConfig->cameraMode>kCameraCockpitCarHidden)gConfig->cameraMode=kCameraChase;
				}
				break;

			case kGameplayOptionsTransparency:
				if(sel&kInterfaceMenuLeftArrow){
					gConfig->hudTransparency-=0.05;
					if(gConfig->hudTransparency<0)gConfig->hudTransparency=0;
				}
				else{
					gConfig->hudTransparency+=0.05;
					if(gConfig->hudTransparency>0.8)gConfig->hudTransparency=0.8;
				}
				break;
				
			case kGameplayOptionsShowPlayerNames:
				gConfig->showPlayerNames=!gConfig->showPlayerNames;
				break;

			case kGameplayOptionsReturn:
			case kInterfaceMenuEsc:
			case kInterfaceMenuOK:
				exit=true;
				break;
		}
	}while(!exit);

	strcpy(gConfig->playerName,menu.items[kGameplayOptionsName].type);

	InterfaceDisposeMenu(&menu);
}

enum{
	kAudioOptionsVolume,
	kAudioOptionsInterfaceSounds,
	kAudioOptionsInputITunesNext,
	kAudioOptionsInputITunesPrev,
	kAudioOptionsInputITunesPlay,
	kAudioOptionsReturn,
	kNumAudioOptionsButtons
};

void InterfaceAudioOptions()
{
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,kNumAudioOptionsButtons,"Audio Options");

	char itemStrings[][256]={"Volume:",
		"Interface Sounds:",
		"iTunes next song key",
		"iTunes previous song key",
		"iTunes play/pause key",
		"Return to previous menu",
		""
		};
	for(int i=0;i<menu.numItems;i++)
		strcpy(menu.items[i].label,itemStrings[i]);

	menu.items[kAudioOptionsReturn-1].lineSpacing*=1.5;
	menu.items[kAudioOptionsVolume].flags|=kInterfaceMenuItemArrowInput|kInterfaceMenuItemSlider;
	menu.items[kAudioOptionsInterfaceSounds].flags|=kInterfaceMenuItemArrowInput;

	int exit=false;

	for(int i=0;i<kAudioOptionsReturn;i++)
	{
		menu.items[i].size*=0.75;
		menu.items[i].lineSpacing*=0.75;
	}
	
	menu.background=FileGetReference("background-options.tif");
	menu.RenderCallback=InterfaceRenderReplay;

	for(int i=kAudioOptionsInputITunesNext;i<=kAudioOptionsInputITunesPlay;i++)
		if(gConfig->keys[kInputITunesNext+i-kAudioOptionsInputITunesNext].controllerID1)
			sprintf(menu.items[i].label,"%s:\255#a\255\t%s\t%s",itemStrings[i],gConfig->keys[kInputITunesNext+i-kAudioOptionsInputITunesNext].identifier,gConfig->keys[kInputITunesNext+i-kAudioOptionsInputITunesNext].controllerIdentifier);		
		else
			sprintf(menu.items[i].label,"%s:\255#a\255\t%s",itemStrings[i],gConfig->keys[kInputITunesNext+i-kAudioOptionsInputITunesNext].identifier);		
	menu.items[kAudioOptionsVolume].sliderPos=gConfig->soundVolume;

	InterfaceMenuZoomAnimation(&menu,-1,true);
	do{
		for(int i=kAudioOptionsInputITunesNext;i<=kAudioOptionsInputITunesPlay;i++)
			if(gConfig->keys[kInputITunesNext+i-kAudioOptionsInputITunesNext].controllerID1)
				sprintf(menu.items[i].label,"%s:\255#a\255\t%s\t%s",itemStrings[i],gConfig->keys[kInputITunesNext+i-kAudioOptionsInputITunesNext].identifier,gConfig->keys[kInputITunesNext+i-kAudioOptionsInputITunesNext].controllerIdentifier);		
			else
				sprintf(menu.items[i].label,"%s:\255#a\255\t%s",itemStrings[i],gConfig->keys[kInputITunesNext+i-kAudioOptionsInputITunesNext].identifier);		

		menu.items[kAudioOptionsVolume].sliderPos=gConfig->soundVolume;
		sprintf(menu.items[kAudioOptionsInterfaceSounds].label,"Interface Sounds: \255#a\255%s",gConfig->interfaceSounds?"On":"Off");
			
		int sel=InterfaceGetUserMenuSelection(&menu);
		switch(menu.initialSelection=(sel&kInterfaceMenuItemMask))
		{
			case kAudioOptionsVolume:
				if(sel&kInterfaceMenuLeftArrow){
					gConfig->soundVolume-=0.1;
					if(gConfig->soundVolume<0)gConfig->soundVolume=0;
				}
				else{
					gConfig->soundVolume+=0.1;
					if(gConfig->soundVolume>1)gConfig->soundVolume=1;
				}
				SoundReInit();
				break;
				
			case kAudioOptionsInterfaceSounds:
				gConfig->interfaceSounds=!gConfig->interfaceSounds;
				break;
				
			case kAudioOptionsInputITunesNext:
			case kAudioOptionsInputITunesPrev:
			case kAudioOptionsInputITunesPlay:
				{
					while(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter));

					menu.initialSelection=sel;
					char keyString[80];
					sprintf(keyString,"Press the new Key or Button for '%s'\n (Or press delete to clear)",itemStrings[sel]);
					InterfaceDrawStrings("Assign new Key",keyString,kFileErr);

					GetInput(gConfig->keys+kInputITunesNext+menu.initialSelection-kAudioOptionsInputITunesNext);
					
					int interfaceKeyPressed;
					do{
						interfaceKeyPressed=false;
						for(int i=kInterfaceKeyUp;i<kInterfaceNumKeys;i++)
							if(GetInterfaceKey(i))
								interfaceKeyPressed=true;
						if(GetButtonInput(kInputITunesNext)||GetButtonInput(kInputITunesPlay))
							interfaceKeyPressed=true;
					}while(interfaceKeyPressed);
				}
				break;
				
			case kAudioOptionsReturn:
			case kInterfaceMenuEsc:
			case kInterfaceMenuOK:
				exit=true;
				break;
		}
	}while(!exit);
	
	InterfaceDisposeMenu(&menu);
}


enum{
	kOptionsGameplay,
	kOptionsControls,
	kOptionsAnalougeControls,
	kOptionsTaunts,
	kOptionsVideo,
	kOptionsAudio,
	kOptionsReturn,
	kNumOptionsButtons
};

void InterfaceOptions()
{
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,kNumOptionsButtons,"Options");

	char itemStrings[][32]={"Gameplay","Controls","Analog Controls","Multiplayer Taunts","Video","Audio","Return to previous menu"};

	for(int i=0;i<menu.numItems;i++)
	{
		strcpy(menu.items[i].label,itemStrings[i]);
		menu.items[i].size*=1.15;
		menu.items[i].lineSpacing*=1.15;
	}

	menu.items[kOptionsReturn-1].lineSpacing*=1.5;

	menu.background=FileGetReference("background-options.tif");
	menu.RenderCallback=InterfaceRenderReplay;
	
	int exit=false;
	do{
		InterfaceMenuZoomAnimation(&menu,-1,true);
		switch(menu.initialSelection=InterfaceGetUserMenuSelection(&menu))
		{
			case kOptionsGameplay:
				InterfaceGameplayOptions();
				break;
			case kOptionsVideo:
				InterfaceVideoOptions();
				break;
			case kOptionsControls:
				InterfaceControlOptions();
				break;
			case kOptionsAnalougeControls:
				InterfaceAnalogueControlOptions();
				break;
			case kOptionsTaunts:
				InterfaceTauntOptions();
				break;
			case kOptionsAudio:
				InterfaceAudioOptions();
				break;
				
			case kOptionsReturn:
			case kInterfaceMenuEsc:
				exit=true;
				break;
		}
	}while(!exit);
	InterfaceDisposeMenu(&menu);
	WriteOutFile(FileGetReference(kConfigFileName),gConfig,kParserTypeConfigDesc);
}
