


/////////////////////////////
//	Main class for slap games
function CSlapGames(objectName,oAjaxQueue,setUserID,setGameID,setSessionID,oGameName)
{
	//	General Vars
	this.oName=objectName;
	this.ajaxes=oAjaxQueue;
	this.ajaxBlocking=false;
	this.userID=setUserID;
	this.sessionID=setSessionID;
	this.gameID=setGameID;
	this.oGameName=oGameName;
	
	//	The game status/state
	this.gameStatus=null;
	this.gameState=null;
	this.currentGameFrame=0;
	this.lastReceivedGameFrame=0;
	this.gamePlayers=null;
	this.lastPlayerCount=0;
	this.totalBytesReceived=0;

	//	Func
	this.DebugWindow=CSlapGames_DebugWindow;
	this.ShortHandToArrayEval=CSlapGames_ShortHandToArrayEval;
	this.ControlTimer=CSlapGames_ControlTimer;
	this.InitGameTimers=CSlapGames_InitGameTimers;
	
	this.UpdatePreGamePlayerList=CSlapGames_UpdatePreGamePlayerList;
	
	this.HandleIncomingAJData=CSlapGames_HandleIncomingAJData;
	
	this.ReceiveGameStatus_AJ=CSlapGames_ReceiveGameStatus_AJ;
	this.ProcessGameStatus=CSlapGames_ProcessGameStatus;
	
	this.ReceivePlayerList_AJ=CSlapGames_ReceivePlayerList_AJ;
	this.ProcessPlayerList=CSlapGames_ProcessPlayerList;
	
	this.ReceiveGameState_AJ=CSlapGames_ReceiveGameState_AJ;
	this.ProcessGameState=CSlapGames_ProcessGameState;
	
	this.KickPlayer_AJ=CSlapGames_KickPlayer_AJ;
	
	this.SendMove=CSlapGames_SendMove;
}

///////////////////////////////////////////
//	Loop that spawns off tasks at intervals
function CSlapGames_ControlTimer(callBack,milliInterval)
{	
	var toEval='this.'+callBack+'();';
	eval(toEval);

	//	Cause the loop to continue
	var newTimeout=this.oName+'.ControlTimer(\''+callBack+'\','+milliInterval+');';
	setTimeout(newTimeout,milliInterval);
}

////////////////////////////////
//	Controls timers for the game
function CSlapGames_InitGameTimers()
{
	//	With game status giving back such small
	//	packets, and gamestate now only refreshing
	//	if gamestatus specifies a new frame,
	//	we can set this alot smaller now
	this.ControlTimer('ReceiveGameStatus_AJ',2000);
}

//////////////////////
//	Performs an update
function CSlapGames_UpdatePreGamePlayerList()
{		
	var oList=document.getElementById('PreGamePlayerList');
	var toSet='';
	var tempID;

	this.DebugWindow('inside updatepregameplayerlist');
	
	if(!oList){
		this.DebugWindow('updatepregameplayers exit bad oList');
		return;
	}

	////////////////////////////////////////////
	//	Now we can build and set that new string
	toSet+='<ul>';
	
	//	If we also have the game state, show
	//	how many open slots we have
	if(this.gameState){
		toSet+='<div>(Slots left: '+this.gameState['openSlots']+')</div>';
	}
	
	
	for(var a=0;a<this.gamePlayers.length;a++){
		
		tempID=this.gamePlayers[a]['info']['userID'];
		
		toSet+="<li>";
		
		toSet+=this.gamePlayers[a]['info']['displayName'];
		if(this.gameState['hostID']==this.userID && tempID!=this.userID){
			toSet+=
				"&nbsp;&nbsp;"
				+"<a href=\"javascript: "+this.oName+".KickPlayer_AJ('"+tempID+"');\">"
				+"(kick)"
				+"</a>";
		}
		
		toSet+='</li>';
	}
	
	toSet+='</ul>';	

	//	Apply the new text
	oList.innerHTML=toSet;
	
	return;
}

/////////////////////////////////////////
//	Kick player using ajax call to server
function CSlapGames_KickPlayer_AJ(userID)
{
	if(!confirm('Are you sure you want to kick this player?')){
		return;
	}
	
	var request='?Action=AJKickPlayer&Session='+this.sessionID+'&Player='+userID;
	
	this.ajaxes.MakeGetRequest(request);
	
	return;
}

//////////////////////////////
//	Processes incoming AJ data
function CSlapGames_HandleIncomingAJData(data,unblockAJ)
{
	var toEval;
	
	//this.DebugWindow(data);
	
	////////////
	//	Unblock?
	if(unblockAJ){
		this.ajaxBlocking=false;
	}
	//	If data is bad, return
	if(!data){
		return false;
	}
	if(!data.length){
		return false;
	}
	
	//	Remember data length
	this.totalBytesReceived+=data.length;
	this.DebugWindow('HandleIncomingAJData(): data.length='+data.length+', total='+this.totalBytesReceived);
	
	//	The data is in our own shorthand,
	//	so expand it to an eval statement
	toEval=this.ShortHandToArrayEval(data);
	var tempArray=null;
	eval(toEval);
	
	return tempArray;
}

////////////////////////
//	Grab the game status
function CSlapGames_ReceiveGameStatus_AJ()
{
	//	If we're already waiting for ajax to get back to us, just return
	if(this.ajaxBlocking){
		return;
	}
	else{
		this.ajaxBlocking=true;
	}
	
	this.ajaxes.MakeGetRequest(
		'?Action=AJGetGameStatus&Session='+this.sessionID,
		this.oName+'.ProcessGameStatus'
		);
}

//////////////////////
//	Processes messages
function CSlapGames_ProcessGameStatus(data)
{
	/////////////////////
	//	Get array of data
	if(this.gameStatus){
		delete this.gameStatus;
	}
	this.gameStatus=this.HandleIncomingAJData(data,false);
	if(!this.gameStatus){
		return;
	}

	///////////////////////////////
	//	Actions based on the status	
	switch(this.gameStatus['code'])
	{
		case 'badsession':
			alert(this.gameStatus['text']+'\r\n\r\n'+this.gameStatus['description']);
			window.location='?Action=ShowGameTables&Game='+this.gameID;
			return;
			break;
			
		case 'hostleft':
			alert(this.gameStatus['text']+'\r\n\r\n'+this.gameStatus['description']);
			window.location='?Action=ShowGameTables&Game='+this.gameID;
			return;
			break;
			
		case 'kicked':
			alert('You have been kicked from this session !!!');
			window.location='?Action=ShowGameTables&Game='+this.gameID;
			return;
			break;
			
		case 'waitingtostart':
		
			//	Hardcode to save bandwidth
			this.gameStatus['text']='Waiting to start...';
			this.gameStatus['description']='The game is set up and we are now waiting for the host to press start.';
			break;
			
		case 'playing':
		
			//	Hardcode to save bandwidth
			this.gameStatus['text']='Playing';
			this.gameStatus['description']='This game is in session.';
			
			//	If we're playing, but we aren't on the play page, bounce
			if(!this.oGameName){
				window.location='?Action=PlayGame&Session='+this.sessionID;
				return;
			}
			break;
	}
	
	///////////////////////////
	//	Set the game status div
	var toSet='';
	toSet+='<div><b>Game Status: </b>'+this.gameStatus['text']+'</div>';
	toSet+='<div><small>'+this.gameStatus['description']+'</small></div>';
	toSet+='<div><small><i>Code = \''+this.gameStatus['code']+'\'';
	toSet+=', frame = '+this.gameStatus['frame']+'</i></small></div>';
	var o=document.getElementById('GameStatus');
	if(o){
		o.innerHTML=toSet;
	}
	else{
		alert('No game status div !');
	}
	
	/////////////////////////////////////////
	//	We now get to do one of the following
	//	1. Ask for updated game state,
	//	2. Ask for updated players hash
	//	3. Do nothing
	//	Order matters, since we need the state
	//	before blitting the first player list
	if(this.currentGameFrame!=this.gameStatus['frame']){
		this.currentGameFrame=this.gameStatus['frame'];
		this.ReceiveGameState_AJ();
		this.DebugWindow('gameStatus says we need an updated game state2');
	}
	else if(this.lastPlayerCount!=this.gameStatus['playerCount']){
		this.lastPlayerCount=this.gameStatus['playerCount'];
		this.ReceivePlayerList_AJ();
		this.DebugWindow('gameStatus says we need an updated player count2');
	}
	else{
		//	Otherwise we're done and are now free for another update
		this.ajaxBlocking=false;
	}
	
	return;
}

////////////////////////////////
//	Asks AJ for the players hash
function CSlapGames_ReceivePlayerList_AJ()
{
	this.ajaxes.MakeGetRequest(
		'?Action=AJGetGamePlayers&Session='+this.sessionID,
		this.oName+'.ProcessPlayerList'
		);
}

/////////////////////////////
//	Processes the player list
function CSlapGames_ProcessPlayerList(data)
{
	/////////////////////
	//	Get array of data
	if(this.gamePlayers){
		delete this.gamePlayers;
	}
	this.gamePlayers=this.HandleIncomingAJData(data,true);
	if(!this.gamePlayers){
		return;
	}
	
	//	Update pre-game player display
	this.UpdatePreGamePlayerList();

	/////////////////////////////////
	//	Feed data to our game object?
	if(this.oGameName){
		toEval=this.oGameName+'.FeedGamePlayers(this.gamePlayers);';
		eval(toEval);
	}
	
	return;
}

////////////////////////
//	Grabs the game state
function CSlapGames_ReceiveGameState_AJ()
{
	this.ajaxes.MakeGetRequest(
		'?Action=AJGetGameState&Session='+this.sessionID,
		this.oName+'.ProcessGameState'
		);
}

//////////////////////////
//	Process our game state
function CSlapGames_ProcessGameState(data)
{
	/////////////////////
	//	Get array of data
	if(this.gameState){
		delete this.gameState;
	}
	this.gameState=this.HandleIncomingAJData(data,true);
	if(!this.gameState){
		return;
	}

	/////////////////////////////////
	//	Feed data to our game object?
	if(this.oGameName){
		toEval=this.oGameName+'.FeedGameState(this.gameState);';
		eval(toEval);
	}

	//	Update game frame number
	this.lastReceivedGameFrame=this.gameState['frame'];	
	this.DebugWindow('Processed game state frame '+this.gameState['frame']);
	
	return;
}

//////////////////////////////////////
//	Sends a damn move string to server
function CSlapGames_SendMove(str)
{
	var moveURL='?Action=AJSendMove&Session='+this.sessionID+'&Move='+escape(str);
	
	this.ajaxes.MakeGetRequest(
		moveURL,
		this.oName+'.ProcessGameState'
		);
}

//////////////////////////////////////
//	Function to decode the shorthand,
//	so the data doesn't seem as large
//	as the first way it was being done
function CSlapGames_ShortHandToArrayEval(string)
{	
	var toReturn="";

	var done=false;
	var char;
	var len=string.length;
	var levels=new Array();
	var strLevels=false;
	var newArrBuild=false;
	var key="";
	var val="";
	var tempString="";
	
	for(var a=0;a<len;a++){
		
		char=string.substr(a,1);

		//	Rebuld levels?
		if(strLevels==false){
			strLevels="";
			for(var l=0;l<levels.length;l++){
				if(l==0){
					strLevels+=levels[l];
				}
				else{
					strLevels+="['"+levels[l]+"']";
				}
			}
			
			if(newArrBuild){
				toReturn+="\n"+strLevels+"=new Array();";
				delete newArrBuild;
				newArrBuild=false;
			}
		}
		
		//	Choose what to do
		switch(char)
		{
			case '[':
				//	Useless haha
				break;
			
			case ':':
				levels[levels.length]=tempString;
				strLevels=false;
				newArrBuild=levels;
				tempString="";
				key="";
				break;
				
			case '=':
				key=tempString;
				tempString="";
				break;
				
			case ']':
				//	Don't break so we can fall to ','
				
			case ',':
				if(key!=""){
					
					//	Prepare value
					val=unescape(tempString);
					val=val.replace(/'/g,"\\'");
					val=val.replace(/\"/g,"\\\"");
					val=val.replace(/\n/g,"\\n");
					toReturn+="\n"+strLevels+"['"+key+"']=\""+val+"\";";
				}
				tempString="";
				key="";
				if(char=="]"){
					strLevels=false;
					levels.pop();
				}
				break;
				
			default:
				tempString+=char;
				break;
		}
	}
	
	return toReturn;
}

//////////////
//	Debug help
function CSlapGames_DebugWindow(str1,oError)
{
	var o;
	var toSet;
	
	o=document.getElementById('DebugWindow');
	if(!o){
		return false;
	}

	//	Grab existing text
	toSet=o.value;
	
	toSet+='\n---------------------\n';	
	toSet+="(CSlapGames) ";
	toSet+=str1;
	
	//	Maybe add some info on the error
	if(oError){
		toSet+=
			'\n\n'
			+"Error name: "+oError.name
			+'\n'
			+"Error message: "+oError.message;
	}

	//	Set the text
	o.value=toSet;
	
	return true;
}

//+++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++



