#include <string.h>
#include <stdio.h>
#include "fileio.h"
#include "interfaceutil.h"
#include "gameinitexit.h"
#include "gameframe.h"
#include "challenges.h"
#include "config.h"
#include "carphysics.h"
#include "gametime.h"
#include "gamesystem.h"
#include "controls.h"
#include "carselection.h"
#include "writeout.h"
#include "environment.h"
#include "renderframe.h"
#include "text.h"
#include "screen.h"
#include "log.h"
#include "interface.h"
#include "textures.h"
#include "gamesound.h"
#include "reg_tool_3.h"

int HasChallengeRequirements(int requirements,int hasReq)
{
	for(int i=0;i<16;i++)
		if(((((unsigned int)requirements)>>(i*2))&0x3)>((((unsigned int)hasReq)>>(i*2)&0x3)))	
			return false;
	return true;
}

void ChallengeRenderCallback(tChallenge *chal,int selection,void *menu)
{
	InterfaceRenderReplay(NULL,selection,menu);
	char info[1024];
	tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(chal->car,kParserTypeCarDesc,sizeof(tCarDefinition));
	sprintf(info,"Car: %s\n\n\255goldmedal.pct\255 Gold: %d:%02d'%02d\n\255silvermedal.pct\255 Silver: %d:%02d'%02d\n\255bronzemedal.pct\255 Bronze: %d:%02d'%02d"
		,car->carName
		,(int)chal->goldTime/60,(int)chal->goldTime%60,(int)(chal->goldTime*100)%100
		,(int)chal->silverTime/60,(int)chal->silverTime%60,(int)(chal->silverTime*100)%100
		,(int)chal->bronzeTime/60,(int)chal->bronzeTime%60,(int)(chal->bronzeTime*100)%100
		);

	TextPrintfToBufferFormated(Vector(0.3,0.6),0.035,kTextAlignLeft|kTextAutoWrap,info);
	TextPrintfToBufferFormated(Vector(-0.9,-0.3),0.035,kTextAlignLeft|kTextAutoWrap,chal->description);
}

enum{
	kTryChallengeItem,
	kShowReplayItem,
	kReturnItem
};
extern int gReggieConnected;
int TrackerConnect();
void RunChallenge(tChallenge *chal,int index)
{
	if(!gReggieConnected&&gConfig->registerLapTimes)
	{
		InterfaceDrawStrings("Connecting to Lap Times Server...","One moment, please.",kFileErr);
		TrackerConnect();
	}
	tGameInfo gInfo;
	InitGInfo(&gInfo);
	gInfo.numPlayers=1;
	gInfo.reverse=chal->reverse;
	gInfo.environment=chal->environment;
	gInfo.numLaps=1;
	gInfo.map=chal->map;
	gInfo.maxTime=chal->bronzeTime;
	gInfo.silverTime=chal->silverTime;
	gInfo.goldTime=chal->goldTime;
	gInfo.playerCars[0]=chal->car;
	gInfo.playerColors[0]=chal->color;
	gLocalRecord=gConfig->challengeRecords[index];
	int result=RunGame(&gInfo);
		
	int oldChallengeData=gConfig->challengeData;
	if(result!=-1)
	{
		if(result-kStartGameDelaySeconds*kFPS<gConfig->challengeRecords[index]||gConfig->challengeRecords[index]==0)
			gConfig->challengeRecords[index]=result-kStartGameDelaySeconds*kFPS;
		if(result*kFrameTime<=chal->goldTime+kStartGameDelaySeconds)
			gConfig->challengeData|=3<<(index*2);
		else if(result*kFrameTime<=chal->silverTime+kStartGameDelaySeconds)
		{
			if((gConfig->challengeData&(3<<(index*2)))<(2<<(index*2)))
				gConfig->challengeData=(gConfig->challengeData&~(3<<(index*2)))|(2<<(index*2));
		}
		else if(result*kFrameTime<=chal->bronzeTime+kStartGameDelaySeconds)
		{
			if((gConfig->challengeData&(3<<(index*2)))<(1<<(index*2)))
				gConfig->challengeData=(gConfig->challengeData&~(3<<(index*2)))|(1<<(index*2));
		}
	}
	if(gConfig->challengeData!=oldChallengeData)
	{
		gConfig->dbIndex=gConfig->challengeData^0xdeadbeef;
	//	WriteOutFile(FileGetReference("config.cfg"),gConfig,kParserTypeConfigDesc);
		for(int i=0;i<gFileTableSize;i++)
			if(char *extension=FileGetExtension(i))
				if(!_stricmp(extension,kFileTypeCarDefinition))
				{
					tCarDefinition *car=(tCarDefinition*)FileGetParsedDataPtr(i,kParserTypeCarDesc,sizeof(tCarDefinition));
					if(HasChallengeRequirements(car->challengeRequirements,gConfig->challengeData)>HasChallengeRequirements(car->challengeRequirements,oldChallengeData))
					{
						float startTime=TimeGetSeconds();									
						while((GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter)||GetInterfaceKey(kInterfaceKeyEsc)));
						float curTime;				
						
						do{	
							SystemPoll(false);
							curTime=TimeGetSeconds()-startTime;
							tEnvironment *oldEnv=gEnvironment;
							tMapEnv* oldMapEnv=gMapEnv;
							gMapEnv=NULL;
							LoadEnvironment(FileGetReference("showroom.senv"));
							SetupLighting();
							InterfaceCarSelectionRender(curTime,&i,1,0,kCarSelectionDisplayMode,0,0,0,0,0,0);
							gMapEnv=oldMapEnv;
							gEnvironment=oldEnv;
						}while(!(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter)||GetInterfaceKey(kInterfaceKeyEsc)));
						FlushKeys();
					}
				}
		
	}					
}

int InterfaceRunChallengeMenu(tChallenge *chal,int index)
{
//	while(GetInterfaceKey(kInterfaceKeyReturn)||GetInterfaceKey(kInterfaceKeyEnter)||GetInterfaceKey(kInterfaceKeyEsc));

	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,3,chal->name);
	strcpy(menu.items[kTryChallengeItem].label,"Try the Challenge");
	strcpy(menu.items[kShowReplayItem].label,"See Demonstration");
	strcpy(menu.items[kReturnItem].label,"Return to previous menu");
	
	if(index>2&&!RT3_IsRegistered())
	{
		strcpy(menu.items[kTryChallengeItem].label,"Not available in demo.");
		menu.items[kTryChallengeItem].flags=kInterfaceMenuItemDisabled;
	}
	menu.items[kShowReplayItem].lineSpacing*=1.5;
	menu.background=FileGetReference("background-clock.tif");
	menu.RenderCallback=(void(*)(void*,int,void*))ChallengeRenderCallback;
	menu.userData=chal;
	menu.itemsYPos=0.6;
	
	int sel;
	do{
		sel=InterfaceGetUserMenuSelection(&menu);
		switch(sel)
		{
			case kTryChallengeItem:
				//InterfaceTextBufferZoomAnimation(FileGetReference("background-clock.tif"),false);
				RunChallenge(chal,index);
				break;
			case kShowReplayItem:
				LogLoad(chal->replay,&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();			
				break;
		}
	//	menu.initialSelection=sel;
	}while(sel==kTryChallengeItem||sel==kShowReplayItem);
}


void InterfaceChallenge()
{
	tChallengeList *cList=(tChallengeList*)FileGetParsedDataPtr(FileGetReference(kChallengeListFileName),kParserTypeChallengeList,sizeof(tChallengeList));
	
	tInterfaceMenuDescribtion menu;
	InterfaceInitMenu(&menu,cList->numChallenges,"Select a Challenge");

	menu.background=FileGetReference("background-clock.tif");
	menu.RenderCallback=InterfaceRenderReplay;
	menu.scrollEnable=true;
//	strcpy(menu.items[cList->numChallenges].label,"Return to previous menu");
//	menu.items[cList->numChallenges-1].lineSpacing*=1.5;
	
	int exit=false;
	do{
		for(int i=0;i<cList->numChallenges;i++)
		{
			if(!HasChallengeRequirements(cList->challenges[i].requirements,gConfig->challengeData))
				menu.items[i].flags|=kInterfaceMenuItemDisabled;
			else
				menu.items[i].flags&=~kInterfaceMenuItemDisabled;
			if((gConfig->challengeData&(3<<(i*2)))==(3<<(i*2)))
				sprintf(menu.items[i].label,"%s \255goldmedal.pct\255",cList->challenges[i].name);
			else if((gConfig->challengeData&(2<<(i*2)))==(2<<(i*2)))
				sprintf(menu.items[i].label,"%s \255silvermedal.pct\255",cList->challenges[i].name);
			else if((gConfig->challengeData&(1<<(i*2)))==(1<<(i*2)))
				sprintf(menu.items[i].label,"%s \255bronzemedal.pct\255",cList->challenges[i].name);
			else
				strcpy(menu.items[i].label,cList->challenges[i].name);
		}
		
		int i=(menu.initialSelection=InterfaceGetUserMenuSelection(&menu));
		if(i!=kInterfaceMenuEsc&&i!=cList->numChallenges)
			InterfaceRunChallengeMenu(cList->challenges+i,i);
		else exit=true;
	}while(!exit);
	InterfaceDisposeMenu(&menu);
}