//interface.cpp
//the game's main menu screen

#include <OpenGL/gl.h>
#include "gametime.h"
#include <string.h>
#include "fileio.h"
#include "textures.h"
#include "controls.h"
#include "screen.h"
#include "gameinitexit.h"
#include "gameframe.h"
#include "initexit.h"
#include "text.h"
#include "config.h"
#include "interface.h"
#include "carselection.h"
#include "mapselection.h"
#include "random.h"
#include "environment.h"
#include "writeout.h"
#include "challenges.h"
#include "interfaceutil.h"
#include "renderframe.h"
#include "log.h"
#include "gamesystem.h"
#include "gamesound.h"
#include "interfacemultiplayer.h"
#include "tracker.h"

#include "stdtypes.h"
#include "reg_tool_3.h"
#include "rt3_redline.h"

tGameInfo gInterfaceGInfo;

//initializes the user interface
void InterfaceInit()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glLoadIdentity();
	glTranslatef(0.0f,0.0f,-1.0f);
}

void StartBackgroundReplay()
{
	gMapInfo=(tMapInfo*)FileGetParsedDataPtr(gInterfaceGInfo.map,kParserTypeMapInfoDesc,sizeof(tMapInfo));	
	LoadEnvironment(gInterfaceGInfo.environment);
	gInterfaceGInfo.network=false;
	gReplay=true;
	gGameInfo=&gInterfaceGInfo;	
	gReplayAutoCam=true;
	if(!(gGameInfo->numLaps==-1&&gBestLapTime==0))
		gCurrentLapStart=0;
		
	StartReplay();
	gReplayViewedEntityID=0;
/*	gFrameCount=0;
	gGraphFrameCount=0;
	gStartTime=TimeGetSeconds();*/
}

int SelectRaceMode(tFileRef map,int (*TimerCallback)(void*),void *userData)
{
	tMapInfo *mapInfo=(tMapInfo*)FileGetParsedDataPtr(map,kParserTypeMapInfoDesc,sizeof(tMapInfo));
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,5,"Select Gameplay Mode");
	menu.RenderCallback=InterfaceRenderReplay;
	menu.initialSelection=gConfig->arcade;
	strcpy(menu.items[0].label,"Simulation");
	strcpy(menu.items[0].describtion,"Simulation Mode tries to resemble real-life car physics as close as possible. Different cars may handle completely different depending on their mass distribution, drivetrain setup and many other factors.");
	strcpy(menu.items[1].label,"Arcade");
	strcpy(menu.items[1].describtion,"Arcade Mode puts emphasis on playability and easy handling of cars, but is vastly inaccurate compared to real-life physics. Different cars handle quite similar and differ only in their acceleration and top speed characteristics.");
	strcpy(menu.items[2].label,"Turbo Arcade");		
	strcpy(menu.items[2].describtion,"Arcade Mode on steroids.");
	strcpy(menu.items[3].label,"Strict");		
	strcpy(menu.items[3].describtion,"Strict mode is like Simulation mode with modified collision physics to encourage clean racing.");
	strcpy(menu.items[menu.numItems-1].label,"Cancel");
	menu.items[menu.numItems-2].lineSpacing*=1.5;
	menu.imageXScale=kMapImageXStretch;
	menu.imageYScale=kMapImageYStretch;	
	menu.imageXPos+=0.1;
	menu.imageYPos-=0.03;
	menu.TimerCallback=TimerCallback;
	menu.userData=userData;
	menu.image=mapInfo->image;
	menu.descPos=Vector(-0.9,-0.6);
	int sel=InterfaceGetUserMenuSelection(&menu);
	InterfaceDisposeMenu(&menu);	
	return sel==menu.numItems-1||sel==kInterfaceMenuEsc?-1:sel;
}

void InterfaceQuickRace()
{
	tGameInfo gInfo;
	InitGInfo(&gInfo);
	//let user select a map...
	if(InterfaceMapSelection(&gInfo,NULL,NULL,false))
	{
		int raceMode=SelectRaceMode(gInfo.map,NULL,NULL);
		if(raceMode==-1)
			return;
		else
			gConfig->arcade=raceMode;
		gInfo.arcade=gConfig->arcade;
		tFileRef playerCar=gConfig->lastCar;
		UInt8 playerColor=gConfig->lastColor;
		//...and a car...
		if(InterfaceCarSelection(&playerCar,kCarSelectionQuickMode,&playerColor,NULL,NULL,NULL))
		{
			gConfig->lastCar=playerCar;
			gConfig->lastColor=playerColor;

			tMapInfo *mapInfo=(tMapInfo*)FileGetParsedDataPtr(gInfo.map,kParserTypeMapInfoDesc,sizeof(tMapInfo));
			int numPlayers=mapInfo->maxPlayers;
			//...and opponets
			if(InterfaceSelectOpponentCars(&numPlayers,gInfo.playerCars+1,gInfo.playerColors+1,NULL,NULL))
			{
				gInfo.numPlayers=numPlayers+1;
				gInfo.playerID=0;
				gInfo.playerCars[gInfo.playerID]=playerCar;
				gInfo.playerColors[gInfo.playerID]=playerColor;
				//and run the game
				RunGame(&gInfo);
				TeaserScreen();	
			}
		}
	}
}

void InterfaceTimeTrial()
{
	tGameInfo gInfo;
	InitGInfo(&gInfo);
	gInfo.numPlayers=1;
	gInfo.numLaps=-1;
	
	//let user select a map...
	if(InterfaceMapSelection(&gInfo,NULL,NULL,true))
	{
		int raceMode=SelectRaceMode(gInfo.map,NULL,NULL);
		if(raceMode==-1)
			return;
		else
			gConfig->arcade=raceMode;
		gInfo.arcade=gConfig->arcade;
		//...and a car...
		gInfo.playerCars[0]=gConfig->lastCar;
		gInfo.playerColors[0]=gConfig->lastColor;
		if(InterfaceCarSelection(gInfo.playerCars,kCarSelectionQuickMode,gInfo.playerColors,NULL,NULL,NULL))
		{
			gConfig->lastCar=gInfo.playerCars[0];
			gConfig->lastColor=gInfo.playerColors[0];
			gLocalRecord=0;

			for(int i=0;i<gConfig->numPersonalRecords;i++)
				if(gConfig->records[i].map==gInfo.map&&gConfig->records[i].car==gInfo.playerCars[0]
					&&gConfig->records[i].mode==gInfo.arcade&&gConfig->records[i].direction==gInfo.reverse)
					gLocalRecord=gConfig->records[i].time;
					
			RunGame(&gInfo);	
			WriteOutFile(FileGetReference(kConfigFileName),gConfig,kParserTypeConfigDesc);
			TeaserScreen();					
		}
	}
}

void InterfaceOptions();

enum{
	kButtonQuickRace,
	kButtonTimeTrial,
	kButtonMultiplayer,
	kButtonCareer,
	kButtonOptions,
	kButtonAbout,
	kButtonQuit,
	kNumButtons
};

void InterfaceDisplayRegisterName(void *userData,int selection)
{
//	TextPrintfToBufferFormated(Vector(1.0,-0.9),0.03,kTextAlignRight,"%s%s",RT3_IsRegistered()?"Registered to: ":"",RT3_GetDisplayName());
	TextPrintfToBufferFormated(Vector(1.0,0.95),0.03,kTextAlignRight,kVersionString);
	
//	TextPrintfToBufferFormated(Vector(-1.0,-0.9),0.03,kTextAlignLeft,kVersionString);
}

#define kTopSize 0.141
void InterfaceRenderReplay(void *userData,int selection,void *menu)
{
	float *t,v=0;
	static int inited=false;
	if(userData)
		t=((float*)userData);
	else 
		t=&v;
	
	if(gConfig->showReplays)//&&0)
	{
		gBackgroundReplay=true;	
		if(!inited)
		{
			gEnableTextureLoad=false;
			gNumTexturesRequested=0;
			gClipEnable=false;
			RenderFrame(false);
			gClipEnable=true;
			gNumTexturesLoaded=0;
			gEnableTextureLoad=true;
			gDisabledRestart=0;
			
			for(int i=0;i<gFileTableSize;i++)
			{
				if(gFileTable[i].tagged&&!gFileTable[i].parsed)
				{	
					gTexturesQualityModifier=gFileTable[i].tagged+1;
					TexturesSelectTex(i);
					SystemPoll(false);

					glLoadIdentity();
					glTranslatef(0.0f,0.0f,-1.0f);

					glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT);

					glDisable(GL_LIGHTING);
					glDisable(GL_DEPTH_TEST);

					gTexturesQualityModifier=-255;
					TexturesSelectTex(FileGetReference("logo.pct"));				
					glClear(GL_COLOR_BUFFER_BIT);

					glBegin(GL_TRIANGLE_STRIP);								
					glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch,-kBackgroundYStretch);		
					glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch,kBackgroundYStretch); 	
					glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,-kBackgroundYStretch); 	
					glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
					glEnd();


					ScreenBlit();	
					glPopAttrib();
				}
			}
			inited=true;
		}
		ReplayFrame();
		if(gSystemSuspended)
			PauseGame();
		gBackgroundReplay=false;	
	}

	glLoadIdentity();
	glTranslatef(0.0f,0.0f,-1.0f);

	glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_LIGHTING);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	gTexturesQualityModifier=-255;
	
	if(menu)
	{
		if(((tInterfaceMenuDescribtion*)menu)->background!=kFileErr||!gConfig->showReplays)
		{
			if(((tInterfaceMenuDescribtion*)menu)->background!=kFileErr)
				TexturesSelectTex(((tInterfaceMenuDescribtion*)menu)->background);
			else
				TexturesSelectTex(FileGetReference("background.tif"));
				
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
			
			if(!gConfig->showReplays)
				glDisable(GL_BLEND);

			glBegin(GL_TRIANGLE_STRIP);								
			glTexCoord2d(1,1); /*glColor4f(1,1,1,0);*/ glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);		
			glTexCoord2d(1,0); /*glColor4f(1,1,1,0);*/ glVertex2f(kBackgroundXStretch,kBackgroundYStretch); 	
			glTexCoord2d(0,1); /*glColor4f(1,1,1,1);*/ glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); 	
			glTexCoord2d(0,0); /*glColor4f(1,1,1,1);*/ glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
			glEnd();
			glEnable(GL_BLEND);
		}
		
		if(((tInterfaceMenuDescribtion*)menu)->image!=kFileErr)
		{
			TexturesSelectTex(((tInterfaceMenuDescribtion*)menu)->image);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
			
			glColor4f(1,1,1,((tInterfaceMenuDescribtion*)menu)->imageAlpha);
			
			glBegin(GL_TRIANGLE_STRIP);								
			glTexCoord2d(1,1); glVertex2f(((tInterfaceMenuDescribtion*)menu)->imageXPos+((tInterfaceMenuDescribtion*)menu)->imageXScale,((tInterfaceMenuDescribtion*)menu)->imageYPos-((tInterfaceMenuDescribtion*)menu)->imageYScale);		
			glTexCoord2d(1,0); glVertex2f(((tInterfaceMenuDescribtion*)menu)->imageXPos+((tInterfaceMenuDescribtion*)menu)->imageXScale,((tInterfaceMenuDescribtion*)menu)->imageYPos+((tInterfaceMenuDescribtion*)menu)->imageYScale); 	
			glTexCoord2d(0,1); glVertex2f(((tInterfaceMenuDescribtion*)menu)->imageXPos-((tInterfaceMenuDescribtion*)menu)->imageXScale,((tInterfaceMenuDescribtion*)menu)->imageYPos-((tInterfaceMenuDescribtion*)menu)->imageYScale); 	
			glTexCoord2d(0,0); glVertex2f(((tInterfaceMenuDescribtion*)menu)->imageXPos-((tInterfaceMenuDescribtion*)menu)->imageXScale,((tInterfaceMenuDescribtion*)menu)->imageYPos+((tInterfaceMenuDescribtion*)menu)->imageYScale);
			glEnd();
			glColor4f(1,1,1,1);
		}
		
		TexturesSelectTex(FileGetReference("menustripe.tif"));
		
		glBegin(GL_TRIANGLE_STRIP);		
		glTexCoord2d(1,1); glVertex2f((2)*kScreenXPos,	0.7*kScreenYPos);		
		glTexCoord2d(1,0); glVertex2f((2)*kScreenXPos,	1.0*kScreenYPos); 	
		glTexCoord2d(0,1); glVertex2f((-2)*kScreenXPos,0.7*kScreenYPos); 	
		glTexCoord2d(0,0); glVertex2f((-2)*kScreenXPos,1.0*kScreenYPos);
		glEnd();
		
		glDisable(GL_TEXTURE_2D);
		glColor4f(0,0,0,1);
		
		glBegin(GL_TRIANGLE_STRIP);								
		glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);		
		glVertex2f(-kBackgroundXStretch,kBackgroundYStretch); 	
		glVertex2f(-2*kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); 	
		glVertex2f(-2*kBackgroundXStretch,kBackgroundYStretch);
		glEnd();

		glBegin(GL_TRIANGLE_STRIP);								
		glVertex2f(2*kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);		
		glVertex2f(2*kBackgroundXStretch,kBackgroundYStretch); 	
		glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); 	
		glVertex2f(kBackgroundXStretch,kBackgroundYStretch);
		glEnd();

		glColor4f(1,1,1,1);
		glEnable(GL_TEXTURE_2D);

	}
	else if(!gConfig->showReplays)
	{
		glDisable(GL_BLEND);
		TexturesSelectTex(FileGetReference("background.tif"));
		
		glBegin(GL_TRIANGLE_STRIP);								
		glTexCoord2d(1,1); /*glColor4f(1,1,1,0);*/ glVertex2f(kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch);		
		glTexCoord2d(1,0); /*glColor4f(1,1,1,0);*/ glVertex2f(kBackgroundXStretch,kBackgroundYStretch); 	
		glTexCoord2d(0,1); /*glColor4f(1,1,1,1);*/ glVertex2f(-kBackgroundXStretch,kBackgroundYStretch-2*kBackgroundXStretch); 	
		glTexCoord2d(0,0); /*glColor4f(1,1,1,1);*/ glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
		glEnd();
		glEnable(GL_BLEND);
	}

	
	if(*t<0)
		*t=TimeGetSeconds();

	float time=TimeGetSeconds();
	float d=1.5-(time-*t)*2;
	if(d<0)d=0;
	
	if(userData&&!isinf(*t))
	{
		TexturesSelectTex(FileGetReference("menulogo.tif"));
		
		glBegin(GL_TRIANGLE_STRIP);		
		glTexCoord2d(1,1); glVertex2f((0.3-d)*kScreenXPos,	0.7*kScreenYPos);		
		glTexCoord2d(1,0); glVertex2f((0.3-d)*kScreenXPos,	1.0*kScreenYPos); 	
		glTexCoord2d(0,1); glVertex2f((-0.95-d)*kScreenXPos,0.7*kScreenYPos); 	
		glTexCoord2d(0,0); glVertex2f((-0.95-d)*kScreenXPos,1.0*kScreenYPos);
		glEnd();

		TexturesSelectTex(FileGetReference("logo.pct"));
		
		glColor4f(1,1,1,d);
		glBegin(GL_TRIANGLE_STRIP);								
		glTexCoord2d(1,1); glVertex2f(kBackgroundXStretch,-kBackgroundYStretch);		
		glTexCoord2d(1,0); glVertex2f(kBackgroundXStretch,kBackgroundYStretch); 	
		glTexCoord2d(0,1); glVertex2f(-kBackgroundXStretch,-kBackgroundYStretch); 	
		glTexCoord2d(0,0); glVertex2f(-kBackgroundXStretch,kBackgroundYStretch);
		glEnd();

		TextPrintfToBufferFormated(Vector(1.0,-0.9),0.03,kTextAlignRight,"%s%s",RT3_IsRegistered()?"Registered to: ":"",RT3_GetDisplayName());
		TextPrintfToBufferFormated(Vector(1.0,0.88),0.03,kTextAlignRight,kVersionString);
	}
	gTexturesQualityModifier=0;
	glPopAttrib();	
}

int InterfaceConfirmQuit()
{
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,2,"Do you really want to quit?");

	menu.background=kFileErr;
	menu.RenderCallback=InterfaceRenderReplay;
		
	char itemStrings[][32]={"Quit","Cancel"};
	menu.items[0].lineSpacing*=1.3;
	for(int i=0;i<menu.numItems;i++)
		strcpy(menu.items[i].label,itemStrings[i]);

	InterfaceMenuZoomAnimation(&menu,-1,true);
	int sel=InterfaceGetUserMenuSelection(&menu);
	InterfaceDisposeMenu(&menu);
	return !sel;
}

void InterfaceReplayMenu()
{
	tInterfaceMenuDescribtion menu;
	tFileRef logs[kMaxLogs];
	int logCount;
	GetLogs(logs,&logCount);

	InterfaceInitMenu(&menu,logCount,"Choose a replay file to play:");

	menu.background=kFileErr;
	menu.scrollEnable=true;
	menu.RenderCallback=InterfaceRenderReplay;
		
	for(int i=0;i<menu.numItems;i++)
	{
		strcpy(menu.items[i].label,FileGetName(logs[i]));
		menu.items[i].size*=0.7;
		menu.items[i].lineSpacing*=0.7;
	}
	int sel=InterfaceGetUserMenuSelection(&menu);
	InterfaceDisposeMenu(&menu);
	if(sel!=kInterfaceMenuEsc)
	{
		if(!LogLoad(logs[sel],&gInterfaceGInfo))
			LogLoad(FileGetReference("bullit.redlog"),&gInterfaceGInfo);
		gGameEnd=false;
		gGameInfo=&gInterfaceGInfo;
		StartBackgroundReplay();
		
		gEnableTextureLoad=false;
		gNumTexturesRequested=0;
		ReplayFrame();
		RenderFrame(false);
		gNumTexturesLoaded=0;
		gEnableTextureLoad=true;
		gDisabledRestart=0;
		
		for(int i=0;i<gFileTableSize;i++)
		{
			if(gFileTable[i].tagged&&!gFileTable[i].parsed)
			{
	//			InterfaceDrawStatusBar("Loading Textures...",gFileTable[i].name,gNumTexturesLoaded/(float)gNumTexturesRequested);
				if(gNumTexturesRequested>0)
					InterfaceDrawStatusBar("Loading Textures...","Please Wait",gNumTexturesLoaded/(float)gNumTexturesRequested);
				TexturesSelectTex(i);
				SystemPoll(true);
			}
		}
		
		StartBackgroundReplay();
		gFrameCount=gReplayOldFrameCount;
		RunReplay();
		SoundSilence();
		FlushKeys();			
	}
}


//run the applications main loop
void InterfaceMainLoop()
{
	float userData=-1;
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,kNumButtons+1,"");
		
	menu.numItems=kNumButtons;
	char itemStrings[][32]={"Quick Race","Time Trial","Multiplayer","Challenges","Options","About","Quit",""};
	for(int i=0;i<menu.numItems+1;i++)
	{
		strcpy(menu.items[i].label,itemStrings[i]);
		menu.items[i].size*=1.25;
		menu.items[i].lineSpacing*=1.25;
	}
	menu.itemsYPos+=0.05;
	menu.items[kButtonQuit-1].lineSpacing*=1.5;
	menu.easterEggEnable=true;
	menu.userData=&userData;
	menu.background=kFileErr;
	
	tFileRef logs[kMaxLogs];
	int logCount;
	GetLogs(logs,&logCount);
	if(!LogLoad(logs[RandomInt(0,logCount)],&gInterfaceGInfo))
		LogLoad(FileGetReference("bullit.redlog"),&gInterfaceGInfo);

	gGameInfo=&gInterfaceGInfo;
	StartBackgroundReplay();

	menu.RenderCallback=InterfaceRenderReplay;

	//menu.RenderCallback=InterfaceDisplayRegisterName;
	//menu.image=FileGetReference("logo.pct");
	
	int exit=false;
	do{
		
		char *version,*url;
		if(TrackerVersionCheck(&version))
		{
			menu.numItems=kNumButtons+1;
			sprintf(menu.items[kButtonQuit].label,"\255#r\255Upgrade to version %s",version);
			strcpy(menu.items[kNumButtons].label,itemStrings[kButtonQuit]);
		}
		InterfaceMenuZoomAnimation(&menu,-1,true);
		switch(menu.initialSelection=InterfaceGetUserMenuSelection(&menu))
		{
			case kButtonQuickRace:
				InterfaceQuickRace();
				break;
			
			case kButtonTimeTrial:
				InterfaceTimeTrial();
				break;
				
			case kButtonCareer:
				InterfaceChallenge();
				break;
					
			case kButtonMultiplayer://let the user start a multiplayer game
				InterfaceMultiplayerLobby();
				break;
				
			case kButtonOptions://game settings
				InterfaceOptions();
				break;
			
			case kButtonAbout:
				TextScrollFile(FileGetReference("credits.txt"));
				break;
			
			case kInterfaceMenuReplayKey:
				InterfaceReplayMenu();
				break;
				
			case kButtonQuit://leave the main loop
			case kInterfaceMenuEsc:
			case kNumButtons:
				if(menu.initialSelection==menu.numItems-2)
				{
					TrackerGetNewVersion();
					exit=true;
					break;
				}
				if(InterfaceConfirmQuit())
					exit=true;
				break;
		}
	}while(!exit);
	
	InterfaceDisposeMenu(&menu);
}