function PokerGame()
{
	this.players = [];
	this.objPlayerTable = document.getElementById( 'playerListTable' );
	this.objPlayerCountText = document.createTextNode( '' );
	this.objStartingStackText = document.createTextNode( '' );
	document.getElementById( 'startingStackPlaceholder' ).appendChild( this.objStartingStackText );
	this.objAverageStackText = document.createTextNode( '' );
	document.getElementById( 'averageStackPlaceholder' ).appendChild( this.objAverageStackText );
	this.objPlayerTable.appendChild( createHeaderRow( [ 'Name', 'Buy-In', 'Position', '' ] ) );
	this.clock = new PokerClock();
	this.prizePool = new PrizePool( this );
	
	this.initWithValues = function( blindMins, rebuyMins, buyIn, currency, startingStack )
	{
		// Instance variables
		this.currency = currency
		this.buyIn = buyIn;
		this.startingStack = startingStack;
		this.clock.initWithValues( blindMins, rebuyMins );
		this.prizePool.update();
		this.onPlayerCountChanged();
		this.paint();
	};
	
	this.initFromXml = function( xml )
	{
		this.currency = xml.documentElement.getAttribute( 'currency' ).replace( '&pound;', '£' );
		this.buyIn = parseInt( xml.documentElement.getAttribute( 'buyin' ) );
		this.startingStack = parseInt( xml.documentElement.getAttribute( 'startingstack' ) );
		this.clock.initFromXml( xml.documentElement.getElementsByTagName( 'clock' )[0] )
		this.prizePool.initFromXml( xml.documentElement.getElementsByTagName( 'prizepool' )[0] )
		var playerListElement = xml.documentElement.getElementsByTagName( 'playerlist' )[0]
		var playerNodes = playerListElement.getElementsByTagName( 'pokerplayer' );
		for( var i = 0; i < playerNodes.length; i++ )
		{
			var player = new PokerPlayer( this );
			player.initFromXml( playerNodes[i] );
			this.addPlayer( player, false );
		}
		this.paint();
	}
		
	this.paint = function()
	{
		var objPlayerCountPlaceholder = document.getElementById( 'playerCount' );
		objPlayerCountPlaceholder.appendChild( this.objPlayerCountText );
		document.getElementById( 'currencyPlaceholder' ).appendChild( document.createTextNode( this.currency ) );
		document.getElementById( 'buyInPlaceholder' ).appendChild( document.createTextNode( this.buyIn ) );
		document.getElementById( 'blindMinsPlaceholder' ).appendChild( document.createTextNode( this.clock.blindTime / 60 / 1000 ) );
		document.getElementById( 'rebuyMinsPlaceholder' ).appendChild( document.createTextNode( ( this.clock.rebuyTime / 60 / 1000 ) + 'm' ) );
		if ( this.startingStack )
		{
			this.objStartingStackText.nodeValue = this.startingStack;
			
		}
		else
		{
			document.getElementById( 'stackContainer' ).style.display = 'none';
		}
	}
	
	this.getAverageStack = function()
	{
		var playerCount = this.players.length;
		var remainingPlayerCount = playerCount - this.getPlayersOutCount();
		var rebuyCount = this.getRebuyCount();
		if ( remainingPlayerCount > 0 )
		{
			var averageStack = this.startingStack * ( playerCount + rebuyCount ) / remainingPlayerCount;
			return averageStack.toFixed( 0 );
		}
		else
		{
			return 'n/a';
		}	
	}
	
	this.toString = function()
	{
		return 'PokerGame[]';
	};
	
	this.toXml = function( documentContext )
	{
		var pokerGame = documentContext.createElement( 'pokergame' );
		pokerGame.setAttribute( 'currency', this.currency.replace('£','&pound;') );
		pokerGame.setAttribute( 'buyin', this.buyIn );
		pokerGame.setAttribute( 'startingstack', this.startingStack );
		pokerGame.appendChild( this.clock.toXml( documentContext ) );
		pokerGame.appendChild( this.prizePool.toXml( documentContext ) );
		var playerList = documentContext.createElement( 'playerlist' );
		for( var i = 0; i < this.players.length; i++ )
		{
			var player = this.players[i];
			playerList.appendChild( player.toXml( documentContext ) );
		}
		pokerGame.appendChild( playerList );
		return pokerGame;
	}
	
	this.save = function( onGameSaved )
	{
		var dom = newXMLDocument( "request", "" );
		dom.documentElement.setAttribute( "action", "save" );
		var fileName = document.getElementById( "fileName" ).value;
		if ( !fileName )
		{
			onGameSaved( false, "Please specify a filename" );
			return false;
		}
		dom.documentElement.setAttribute( "filename", fileName );
		dom.documentElement.appendChild( this.toXml( dom ) );
		var serializedXML = serialiseXml( dom );
		var client = getXMLHTTPObject();
		function handler() 
		{
			if( client == null || client.readyState == null || client.readyState == 1 )
			{
				return;
			}
			if( client.readyState == 4 && client.status == 200 ) 
			{
				if( client.responseXML != null )
				{
					var success = client.responseXML.documentElement.tagName == "success";
					onGameSaved( success, client.responseXML.documentElement.childNodes[0].nodeValue );				
				}
				else
				{
					onGameSaved( false, client.responseText );
				}
			}
			else if ( client.readyState == 4 && client.status != 200 )
			{
				onGameSaved( false, "Failed to save. HTTP Status: " + client.status + ". Please retry" );
			}
		}
		client.onreadystatechange = handler;
		client.open( "POST", AJAX_HANDLER, true );
		client.send( dom );
	}
	
	this.addPlayer = function( pokerPlayer, updatePositions )
	{
		for( var i = 0; i < this.players.length; i++ )
		{
			var player = this.players[i];
			var playerName = player.name;
			if ( playerName.toUpperCase() == pokerPlayer.name.toUpperCase() )
			{
				alert( pokerPlayer.name + ' is already in the game' );
				return false;
			}
		}
		if ( updatePositions )
		{
			for( var i = 0; i < this.players.length; i++ )
			{
				var player = this.players[i];
				if ( player.position != -1 )
				{
					player.position += 1;
				}
			}
		}
		this.players.push( pokerPlayer );
		this.objPlayerTable.appendChild( pokerPlayer.tableRow );
		this.onPlayerCountChanged();
		return true;
	};
	
	this.removePlayer = function( pokerPlayer )
	{
		if ( !confirm( 'Delete ' + pokerPlayer.name + '?' ) )
		{
			return false;
		}		
		// "Undo" the position this player has taken 
		var oldPosition = pokerPlayer.position;
		var topPlayers = this.getTopPlayers();
		for ( var i = oldPosition; i < topPlayers.length; i++ )
		{
			var player = topPlayers[i];
			if ( player )
			{
				player.position += -1;
			}
		}
		this.objPlayerTable.removeChild( pokerPlayer.tableRow );
		var foundIndex = -1;
		for( var i = 0; i < this.players.length; i++ )
		{
			var foundPlayer = this.players[i];
			if ( foundPlayer.name == pokerPlayer.name )
			{
				foundIndex = i;
				break;
			}
		}
		if ( foundIndex != -1 )
		{
			this.players.splice( foundIndex, 1 );
		}
		this.onPlayerCountChanged();
		return true;
	};
	
	this.onPlayerCountChanged = function()
	{
		this.refreshPlayerAppearances();
		this.objPlayerTable.style.display = this.players.length > 0 ? "table" : "none";
		this.objPlayerCountText.nodeValue = this.players.length;
		this.objAverageStackText.nodeValue = this.getAverageStack();
		this.prizePool.update();
	};
	
	this.onPlayerInOrOut = function()
	{
		this.refreshPlayerAppearances();
		this.objAverageStackText.nodeValue = this.getAverageStack();
		this.prizePool.update();
	};

	this.onPrizePoolChange = function()
	{
		for( var i = 0; i < this.players.length; i++ )
		{
			var player = this.players[i];
			if ( player.position != -1 )
			{
				player.refreshAppearance();
			}
		}	
	};
	
	this.onBuyInAltered = function()
	{
		this.objAverageStackText.nodeValue = this.getAverageStack();
	}
	
	this.setPlayerIsPlaying = function( pokerPlayer, isPlaying )
	{
		pokerPlayer.setIsPlaying( isPlaying );
		if ( isPlaying )
		{
			var oldPosition = pokerPlayer.position;
			pokerPlayer.position = -1;
			var topPlayers = this.getTopPlayers();
			for ( var i = 0; i < oldPosition; i++ )
			{
				var player = topPlayers[i];
				if ( player )
				{
					player.position += 1;
				}
			}
		}
		else
		{
			// This player has left the game, so give him the max position
			pokerPlayer.position = this.players.length - this.getPlayersOutCount() - 1;
		}
		this.onPlayerInOrOut();
	};
	
	this.getPlayersOutCount = function()
	{
		var playersOutCount = 0;
		for ( var i = 0; i < this.players.length; i++ )
		{
			var player = this.players[i];
			if ( player.position != -1 )
			{
				playersOutCount++
			}
		}
		return playersOutCount;
	}
	
	this.getTotalBuyIn = function()
	{
		var totalBuyIn = 0;
		for( var i = 0; i < this.players.length; i++ )
		{
			var player = this.players[i];
			totalBuyIn += player.buyIn;
		}
		return totalBuyIn;
	};
	
	this.getRebuyCount = function()
	{
		var rebuyCount = 0;
		for( var i = 0; i < this.players.length; i++ )
		{
			var player = this.players[i];
			if ( player.buyIn == 0 )
			{
				continue;
			}
			rebuyCount += ( player.buyIn / this.buyIn ) - 1;
		}
		return rebuyCount;
	}
	
	this.getTopPlayers = function()
	{
		var topPlayers = new Array( this.players.length );
		for( var i = 0; i < this.players.length; i++ )
		{
			var player = this.players[i];
			if ( player.position != -1 )
			{
				topPlayers[ player.position ] = player;
			}
		}
		return topPlayers;		
	}	
	
	this.refreshPlayerAppearances = function()
	{
		for( var i = 0; i < this.players.length; i++ )
		{
			var player = this.players[i];
			player.refreshAppearance();
		}
	};
}