<html>
	<head>
		<title>Memory extended</title>
		<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
        <style type="text/css">
        * {
          margin:0;
          padding:0;
        }
		
		.box {
			float: left;
			height:50px;
			width: 50px;
			border: 5px solid #999;
			margin: 0 15px 15px 0;
			padding: 5px;
			background:black;
			text-align:center;
			color:black;
		}
		
		.clearer {
			clear:both;
		}
        </style>
		<script type="text/javascript" src="http://livebot.msgweb.nl/_api/extended_activities.js"></script>
		<script type="text/javascript">
			// set up browser event handlers
			var rows = 6;
			var stage = [];
			var myID = 0;
			var firstCard = null;
			var secondCard = null;
			var currentUser = 0;
			var colors = [];
			var scores = [];
			var numUsers = 0;
			var newGameMsgPending = 0;
			
			// Shorthand for document.getElementById
            function $(id) {
                return document.getElementById(id);
            }
			
			function dbg(msg)
			{
				ActivityExtender.Debug(msg);
			}
			// Someone left the activity.
			function Channel_OnRemoteAppClosed(user)
			{
				dbg(user.id+'--'+currentUser);
				if(stage.length == 0 && isFirstActiveUser())
				{
					createNewGame();
				}
				else if(user.id == currentUser)
				{
					nextUser();
				}
			}

			// We cannot always use 
			// if(Users.Me == Users.Inviter)
			// to determine whether this user should undertake the first step,
			// since the inviter may have left the activity.
			// Therefor, we create this function to see whether the client is the first active user.
			function isFirstActiveUser()
			{
				for(var i = 0; i <  ext.Users.Count; i++)
				{
					if(ext.Users.Item(i) != null)
					{
						return ext.Users.Item(i) == ext.Users.Me;	
					}
				}
			}

			function createNewGame()
			{
				JSON = makeStage();
				ext.Channel.SendData('map|'+JSON);
				newGame();
			}
			
			function Channel_OnDataReceived()
			{
				var myData = ext.Channel.Data;
				var params = myData.split("|");
				dbg('data: '+myData);
				
				if(params[0] == "map")
				{
					stage = eval(params[1]);
					newGame();	
				} 
				else if (params[0] == "card" && stage.length > 0)
				{
					playCard(parseInt(params[1]), parseInt(params[2]));
				}
				else if (params[0] == "new")
				{
					newGameMsgPending--;
					if( newGameMsgPending == 0 && isFirstActiveUser())
					{
						createNewGame();
					}					
				}
			}
			
			// Hide the 'clicked' cards
			function hideCards()
			{
				firstCard.hide();
				secondCard.hide();
				firstCard.enable();
				secondCard.enable();
				firstCard = secondCard = null;
				nextUser();
			}

			function newGame()
			{
				// If we want to iterate on the players in the game, we do not want to include
				// any of the users who joined in the middle of the game. Those users will wait for the
				// next round to begin. Therefor, we save the current number of users in numUsers.
				numUsers = ext.Users.Count;
				
				scores = new Array();
				colors = ["red", "blue", "green", "yellow", "orange", "white", "pink"];
				
				// Assign the color black to users who left. It won't be used, but otherwise
				// they'll take the nice colors we want to use for active users only :-)
				for(var i = 0; i < ext.Users.Count; i++)
				{
					scores[i] = 0;	
					if(ext.Users.Item(i) == null)
					{
						colors.splice(i,0,"black");
					}
				}
				currentUser = -1;
				nextUser();
				initStage();
			}
			
			// This class will be used to manage the clicked cards.
			function card(mx, my)
			{
				this.x = mx;
				this.y = my;
				this._node = $('card_'+mx+'_'+my);
				
				this.getValue = function()
				{
					return stage[this.x][this.y][0];	
				}
				
				this.enable = function()
				{
					stage[this.x][this.y][1] = 0;
				}
				
				this.disable = function()
				{
					stage[this.x][this.y][1] = 1;
				}
				
				this.show = function()
				{
					this._node.innerHTML = this.getValue();
					this._node.style.background = "white";	
				}
				
				this.hide = function()
				{
					this._node.innerHTML = "-";
					this._node.style.background = "black";	
				}
				
				this.setColor = function(color)
				{
					this._node.style.border = "5px solid "+color;	
				}
			}
			
			
			function playAgainOrNot(play)
			{
				if(play)
				{
					ext.Channel.SendData("new|yes");
					newGameMsgPending--;
					if( newGameMsgPending == 0 && isFirstActiveUser())
					{
						createNewGame();
					}		
				}
				else
				{
					ext.Channel.SendData("new|no");
					ext.CloseApp();
				}
			}
			
			function checkForEnd()
			{
				var totalScore = 0;
				var maxScore = -1;
				var winners = [];
				
				for(var i = 0; i < numUsers; i++)
				{
					if(ext.Users.Item(i) != null)
					{
						totalScore += scores[i];
						if(scores[i] > maxScore)
						{
							maxScore = scores[i];
							winners = [];
							winners.push(i);
						} 
						else if(scores[i] == maxScore)
						{
							winners.push(i);	
						}
					}
				}	
				
				if(totalScore == (rows*rows)/2) // Game has been solved.
				{
					var msg = "";
					
					if(scores[myID] == maxScore)
					{
						msg += "Congratulations, ";
						if(winners.length > 1)
						{
							msg += "you're one of the winners! ";
						}
						else
						{
							msg += " you won this game! ";
						}	
					}
					else
					{
						msg += "Unfortunately you didn't win this game. ";	
					}
					
					newGameMsgPending = 0;
					for(var i = 0; i < numUsers; i++)
					{
						if(ext.Users.Item(i) != null)
						{
							newGameMsgPending++;
						}
					}
											
					msg += "Play again?";
					playAgainOrNot(confirm(msg));			
				}
			}
			
			function playCard(x,y)
			{
				dbg('playcard'+x+'_'+y);
				if(firstCard==null) 
				{
					firstCard = new card(x,y);
					firstCard.disable();
					firstCard.show();
				} 
				else if(secondCard == null) 
				{
					secondCard = new card(x,y);
					secondCard.disable();
					secondCard.show();
					
					if(firstCard.getValue() == secondCard.getValue())
					{
						scores[currentUser]++;	
						firstCard.setColor(colors[currentUser]);
						secondCard.setColor(colors[currentUser]);
						firstCard = secondCard = null;
						checkForEnd();
					} 
					else 
					{
						window.setTimeout("hideCards()", 3000);
					}
				}	
			}
			
			function cardClicked(x, y)
			{
				if(	currentUser != myID || stage[x][y][1] == 1 || (secondCard != null)) 
				{
					return;
				}
				ext.Channel.SendData("card|"+x+"|"+y);	
				playCard(x,y);			
			}
			
			function initStage() {
				
				var html = "";
				
				for(var x = 0; x < rows; x++)
				{
					for(var y = 0; y < rows; y++)
					{
						if(y == 0){
							html += "<br class='clearer' />";
						}
						html += "<div class='box' id='card_"+x+"_"+y+"' onclick='cardClicked("+x+","+y+")'>-</div>";	
					}	
				}
				$('stage').innerHTML = html;
			}
			
			// Create a new random stage, and return the JavaScript Object Notation of the stage
			// so we can easily send it over the Channel object.
			function makeStage()
			{
				var numbers = [];
				for(var i = 0; i < rows*rows*0.5; i++)
				{
					numbers.push(i, i);
				}
				
				var JSON = "[";
				for(var x = 0; x < rows; x++)
				{
					stage[x] = new Array();
					JSON += "\n[";
					
					for(var y = 0; y < rows; y++)
					{
						JSON += "\t[";	
						var index = Math.floor(Math.random()*numbers.length);		
						stage[x][y] = [numbers[index], 0];
						JSON += numbers[index]+", 0";
						if(numbers.length > 1) 
							numbers.splice(index, 1);	
						JSON += "],";
					}	
					JSON = JSON.substr(0, JSON.length-1);
					JSON += "],";	
				}
				JSON = JSON.substr(0, JSON.length-1);
				JSON += "]";
				return JSON;
			}
			
			
			function updateStatus()
			{
				$('status').innerHTML = "Waiting for: <span style='color:"+colors[currentUser]+"'>"+ext.Users.Item(currentUser).EMail+"</span>";
			}
			
			function nextUser() {
				
				if(firstCard != null)
				{
					firstCard.enable();
					firstCard.show();
					firstCard = null;
				}
				
				if(secondCard != null)
				{
					secondCard.enable();
					secondCard.show();
					secondCard = null;
				}
				
				if(currentUser == numUsers - 1)
				{
					currentUser = 0;
				}
				else
				{
					currentUser++;
				}
				
				if(ext.Users.Item(currentUser) == null)
				{
					nextUser();
				}
				else
				{
					updateStatus();
				}					
			}
			
			function Channel_OnRemoteAppsLoaded() {
				for(var i = 0; i < ext.Users.Count; i++)
				{
					if(ext.Users.Item(i) == ext.Users.Me)
					{
						myID = i;
					 	break;	
					}
				}
				
				if(ext.Users.Me == ext.Users.Inviter)
				{
					createNewGame();
				}	
			}
			
			function OnLoadEvent() {
            	ActivityExtender.Initialize();
				ext.Channel.Initialize();
			}
			window.onload = OnLoadEvent;
		</script>
	</head>
	<body>
	   <h4 id="status">Waiting for a new game to begin...</h4>
       <div id="stage"></div>
    </body>
</html>