// TODO: Redo the way the song links work in the chat and playlist.
//       Make the links link to global data and no longer store info in name and id tags like a crazy nut.
var browser;
var xmlHttp=null;
document.onkeypress=onkeyhitDocument;
document.onkeydown=onkeydownDocument;
document.onkeyup=onkeyupDocument;
document.onblur=onblurDocument;
var shiftDown=false;
var ctrlDown=false;
var altDown=false;
var lastUpdate=0;
var lastSend=null;
var nullCounter=0;
var THERMO_RATIO=1.0;
var THERMO_HEIGHT=512;
var THERMO_WIDTH=93;
var LINE_RATIO=0.73;
var LINE_WIDTH=93;
var LINE_STRETCH=1.0;
var LINE_HEIGHT=17;

// Chat altering options
var isAsian=false;
var isCrazy=false;
var isDrunk=false;
var isPirate=false;
var isPirateDay=false;
var isStoned=false;
var isCAPS=false;

// Sounds
var soundOn=true;
var soundGame=null;
var soundChat=null;
var extraSounds=new Array();
var soundParsed=false;
var volume=75;
var flashIsBugged=false;

// Music player
var jukeboxLoaded=false;
var songLength=0;
var loadingNextSong=false;
var songEnded=true;
var youTubeErrorNextSongHandle=null;
var autoPlay=false;
var SONG_INTERVAL=2000;
var currentSongID=-1;
var numMoviesInPlaylist=0;
var currentPlaylistSong=-1;
var shuffleOn=false;

// YouTube API
var STATE_UNSTARTED  = -1;
var STATE_ENDED      = 0;
var STATE_PLAYING    = 1;
var STATE_PAUSED     = 2;
var STATE_BUFFERING  = 3;
var STATE_VIDEO_CUED = 5;

var QUALITY_240  = "small";
var QUALITY_320  = "medium";
var QUALITY_480  = "large";
var QUALITY_720  = "hd720";
var QUALITY_1080 = "hd1080";
var QUALITY_3072 = "highres";

// Chat
var numChatters=0;
var chatters=new Array();
var seed=Math.floor(( Math.random()*3000 ));
var targetName="";
var chatterAdded=false;
//var status=0; <-- Is set in head.

// Flood prevention system for the chat.
var floodCounterFive = 0;
var floodCounterTen = 0;
var floodCounterMinute = 0;
var FLOOD_CAP_FIVE = 3;
var FLOOD_CAP_TEN = 5;
var FLOOD_CAP_MINUTE = 15;

// Emoticons
var icons = new Array();
icons[':)'] = "smile";
icons[':('] = "sad";
icons[':d'] = "bigsmile";
icons[':|'] = "neutral";
icons[':o'] = "gasp";
icons[':p'] = "tongue";
icons['(l)'] = "love";
icons['(i)'] = "idea";
icons['(!)'] = "exclamation";
icons['(*)'] = "star";
icons['(o)'] = "clock";
icons['(li)'] = "lightning";

// Returns element by ID.
function el(e){
  return document.getElementById(e);
}

// Returns a new XML request object.
function newxmlrequest(){
  try{
    return new XMLHttpRequest();
  }
  catch (er){
    try{
      return new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (er){
      try{
	      return new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch (er){
	      alert("Your browser does not support AJAX.");
      }
    }
  }
}

// Initialises size of the page.
function initSize(){
  // Never used.
}

// Iniatialises the sound for the chat.
function initSound(){
  if(!el("chatPane"))
    return;
  
  soundGame=soundManager.createSound('game','audio/game.mp3');
  soundChat=soundManager.createSound('chat','audio/chat.mp3');
  soundManager.setVolume('game',volume);
}

// General initialisation.
function init(){
  setBrowser();
  initSize();
  
  // Make sure game link disables for a few seconds after a click to prevent the double joining bug.
  // BUGGED: Caused link to malfunction.
  /*$("#game_link").click( function(){
    var link=$("#game_link").attr("href");
    $("#game_link").attr("href","");
    $("#game_link").text("This link is now unclickable for 5 seconds, to prevent double clicks.");
    setTimeout(function(){
      $("#game_link").attr("href",link);
      $("#game_link").text(link);
    },5000);
  });*/
  
  // CAPS DAY!
  if(month==6 && day==28 || month==10 && day==22){
    $("body").css("text-transform","uppercase");
    $("#chatInput").css("text-transform","uppercase");
    $("#jf").css("text-transform","uppercase");
    $("#game_link").css("text-transform","none");
    $("#create_a_game").css("margin-left","-5px");
    $("#create_a_game").css("margin-right","-5px");
  }
	
	if(month==9 && day==19){
		isPirateDay=true;
	}
  
  if(el("chatPane")){
    if(window.body) // IE
      window.body.onunload=leaveChat;
    else // FF
      window.onunload=leaveChat;
    
    el("chatInput").focus=false;
    
    chat("<b>Type /help for options. Join an open game, create your own game or observe a running game!</b>");
    
    if(month==6 && day==28){
      chat("<b>HAPPY FIRST CAPS LOCK DAY OF "+year+"!</b>");
    }
    
    if(month==10 && day==22){
      chat("<b>HAPPY SECOND CAPS LOCK DAY OF "+year+"!</b>");
    }
    
    enterChat();
    setInterval(updateChat,4000);
    setInterval(chatCheck,120000);
    updateGames();
    setInterval(updateGames,240000);
    
    // Flood prevention system. 
    setInterval(floodRefreshFive,5000); 
    setInterval(floodRefreshTen,10000); 
    setInterval(floodRefreshMinute,60000);
		
		if((settings&1)==0) // Lobby muted.
			toggleSound();
		
		// Only on New Year's Eve: Fireworks! (You need to include the special files in head.php)
		//toggleFireworks(true);
		//chat("<b style='color: darkred;'>Happy 2013! Click the lobby to launch FIREWORKS! Wooh!</b>");
  }

  if(el("slashTable")){ // Let's clean up that text!
    var slashTable = el("slashTable");
    var cells      = slashTable.getElementsByTagName("td");
    for(var i=0; i<cells.length; i++){
      cells[i].innerHTML = parseCommand( cells[i].innerHTML );
    }
  }
  
  if(el("itemTable")){ // Let's set up the tooltips.
    var itemTable = el("itemTable");
    var images    = itemTable.getElementsByTagName("img");
    var cells     = itemTable.getElementsByTagName("td");
    for(var i=0; i<images.length; i++){
      activateTooltip(cells[i*2+3].innerHTML ,images[i].id);
      cells[i*2+3].innerHTML = parseTooltip(cells[i*2+3].innerHTML);
    }
  }
	
  if(el("skillsTable")){ // Let's set up the tooltips.
    var skillsTable = el("skillsTable");
    var images    = skillsTable.getElementsByTagName("img");
    var cells     = skillsTable.getElementsByTagName("td");
    for(var i=0; i<images.length; i++){
      activateTooltip(cells[i*2+3].innerHTML ,images[i].id);
      cells[i*2+3].innerHTML = parseTooltip(cells[i*2+3].innerHTML);
    }
  }
  
  if(el("classTable")){ // Let's set up the tooltips.
    var classTable = el("classTable");
    var images     = classTable.getElementsByTagName("img");
    
    for(var i=0; i<images.length; i++){
      activateTooltip(el("tooltip"+images[i].id).innerHTML ,images[i].id);
      el("tooltip"+images[i].id).innerHTML = parseTooltip(el("tooltip"+images[i].id).innerHTML);
    }
  }
	
	if($("#jukediv").length==1)
    $("#jukediv").css("visibility","hidden");
  
  if( $("#lobbyHeader").length==1 ){
    $("#lobbyHeader").append("Members in lobby: <span id='numMembers'></span>");
    $("#lobbyHeader").append("Open games: <span id='numOpen'></span>");
    $("#lobbyHeader").append("Running games: <span id='numRunning'></span>");
    $("#lobbyHeader").append("Active players: <span id='numPlayers'></span>");
  }
  
  if( $("#thermo").length==1 ){
    $("#thermo").css("width","100%").css("height",(THERMO_RATIO*THERMO_HEIGHT)+"px").css("position","relative").css("margin-bottom","4px");
    
	var coords=
	"3,512,"+
	"90,512,"+
	"90,430,"+
	"72,430,"+
	"72,4,"+
	"19,4,"+
	"19,430,"+
	"3,430";
	var imgMap="<map name='thermoMap'><area id='thermoMapArea' alt='Thermometer' title='' shape='poly' coords='"+coords+"' /></map>";
	$("#thermo").append(imgMap);
	
    // Place the empty thermometer.
    $("#thermo").append("<div id='thermo_clip_empty'></div>");
    $("#thermo_clip_empty").css("width",(THERMO_RATIO*THERMO_WIDTH)+"px").css("position","absolute").css("left",((200-THERMO_RATIO*THERMO_WIDTH)*0.5)+"px");
    $("#thermo_clip_empty").append("<img id='empty' src='http://www.boardgame-online.com/images/thermo_feb_2012_empty.png' />");
    $("#empty").css("width",(THERMO_RATIO*THERMO_WIDTH)+"px");
    
    // Place the full thermometer and clip it.
    $("#thermo").append("<div id='thermo_clip_full'></div>");
    $("#thermo_clip_full").css("width",(THERMO_RATIO*THERMO_WIDTH)+"px").css("position","absolute").css("left",((200-THERMO_RATIO*THERMO_WIDTH)*0.5)+"px");
    $("#thermo_clip_full").append("<img id='full' src='http://www.boardgame-online.com/images/thermo_feb_2012_full.png' usemap='#thermoMap' />");
    $("#full").css("width",(THERMO_RATIO*THERMO_WIDTH)+"px");
    $("#thermo_clip_full").css("clip","rect("+(THERMO_RATIO*THERMO_HEIGHT)+"px,"+(THERMO_RATIO*THERMO_WIDTH)+"px,"+(THERMO_RATIO*THERMO_HEIGHT)+"px,0px)");
    
    $.ajax({
      url: "http://www.boardgame-online.com/thermo.php",
      type: "post",
      dataType : "xml",
      cache: false,
      success: thermoCallback
    });
  }
  
  if( $("#accountWrapper").length==1 ){
    accountPage();
  }
}

function thermoCallback(responseXML,aStatus){
  if(aStatus=="success"){
    // Get the root.
    xmlDoc=responseXML.getElementsByTagName("x")[0];
    
    if(xmlDoc==null)
      return;
    var isTopGoal = true;
    var highestAmount = 0;
    var total = 0;
    var goalCounter = 0;
    var totalGoals = xmlDoc.childNodes.length - 1;
    for(var inode_counter=0;inode_counter<xmlDoc.childNodes.length;inode_counter++){
      var x=xmlDoc.childNodes[inode_counter];
  	  try{
        switch(x.nodeName){
          case "g":
            var tooltip=x.childNodes[0].nodeValue;
            var amount=parseInt(x.getAttribute("v"));
            // Add this goal to the thermometer.
            if(isTopGoal){
              highestAmount = amount;
              isTopGoal = false;
            }
            var top = (THERMO_HEIGHT-25)-((THERMO_HEIGHT-25)*amount/highestAmount)-8+25;
            if(top<0)
              top=0;
            $("#thermo").append("<img src='http://www.boardgame-online.com/images/thermoline_normal.png' id='goal"+goalCounter+"' />");
            $("#goal"+goalCounter).css("position","absolute").css("width",(LINE_RATIO*LINE_WIDTH)+"px").css("height",(LINE_STRETCH*LINE_HEIGHT)+"px")
                                  .css("left",((200-LINE_RATIO*LINE_WIDTH)*0.5-3)+"px").css("top",top+"px")
                                  .mouseover(function(){$(this).attr("src","images/thermoline_selected.png");})
                                  .mouseout(function(){$(this).attr("src","images/thermoline_normal.png");});
            $("#thermo").append("<div id='goalDiv"+goalCounter+"'></div");
            $("#goalDiv"+goalCounter).css("position","absolute").css("left",(97+LINE_RATIO*LINE_WIDTH*0.5)+"px").width("80px")
                                     .css("top",top+"px").css("text-align","left");
            if(total>=amount){
              tooltip+="<br /><br /><b style='text-decoration: line-through;'>"+"&euro;"+(amount/100.00).toFixed(2)+"</b><br /><b>GOAL REACHED!</b>";
              $("#goalDiv"+goalCounter).html("REACHED!").css("color","#005500");
            }
            else{
							tooltip+="<br /><br /><b>"+"&euro;"+(amount/100.00).toFixed(2)+"</b>";
              $("#goalDiv"+goalCounter).html("&euro;"+(amount/100.00).toFixed(2));
            }
            activateTooltip(tooltip,"goal"+goalCounter);
            goalCounter++;
            break;
          case "t":
            total=x.childNodes[0].nodeValue;
            if(total==0)
              var totalMessage="Feed Us! - No donations so far this month. We're hungry... so hungry... :(";
            else if(total<8000)
              var totalMessage="Total - This month we have a total of &euro;"+(total/100.00).toFixed(2)+" so far!";
            else
              var totalMessage="Total - This month we have a total of &euro;"+(total/100.00).toFixed(2)+" already! Radical! Thanks for keeping us alive, guys!";
						
						if(total==0)
							$("#empty").attr("usemap","#thermoMap");
						activateTooltip(totalMessage,"thermoMapArea");
            break;
        }
	    }
      catch(err){
				chat("JavaScript Error on line "+err.lineNumber+": "+err.toString());
			}
    }
    // Set clip on the full thermometer.
    if(total>=highestAmount){
      var clipTop = THERMO_HEIGHT;
			activateTooltip("We Lurve You! - You are the best! You've reached the highest goal for this month and have therefore earned our lurve! We lurve you like mad!<br /><br />You're all crazy badass, that's what you are!<br /><br /><b>&euro;"+(total/100.00).toFixed(2)+" reached!</b>","thermoMapArea");
		}
    else
      var clipTop = (THERMO_HEIGHT-25)-((THERMO_HEIGHT-25)*total/highestAmount)+25;
    if(clipTop<0)
      clipTop=0;
		if(total<highestAmount)
			$("#thermo_clip_full").css("clip","rect("+clipTop+"px,"+(THERMO_RATIO*THERMO_WIDTH)+"px,"+(THERMO_RATIO*THERMO_HEIGHT)+"px,0px)");
		else
			$("#thermo_clip_full").css("clip","rect("+0+"px,"+(THERMO_RATIO*THERMO_WIDTH)+"px,"+(THERMO_RATIO*THERMO_HEIGHT)+"px,0px)");
  }
}

// Sets the browser variable.
function setBrowser(){
  browser=navigator.appName;
}

// Handles keyboard input.
function onkeyhitDocument(e){
  var evt = (e) ? e : window.event;
  var charCode = (evt.keyCode) ? evt.keyCode : evt.which;
  if(charCode == 13){
    if (el("Login")){
      getsalt();
    }
    if(el("jf")){
      var focusedInputs = $("#jf:focus");
      if (focusedInputs != null && focusedInputs.length > 0){
        // Search Music has focus.
        $("#jfButton").click();
      }
    }
  }
  // Detect shift, alt, ctrl.
}

// Checks if a modifier key is down.
function onkeydownDocument(e){
  var charCode = (e.keyCode) ? e.keyCode : e.which;
  if(charCode==16)
    shiftDown=true;
  else if(charCode==17)
    ctrlDown=true;
  else if(charCode==18)
    altDown=true;
}

// Checks if a modifier key is up.
function onkeyupDocument(e){
  var charCode = (e.keyCode) ? e.keyCode : e.which;
  if(charCode==16)
    shiftDown=false;
  else if(charCode==17)
    ctrlDown=false;
  else if(charCode==18)
    altDown=false;
}

// Activates when the page is no longer focused.
function onblurDocument(e){
  shiftDown=false;
  ctrlDown=false;
  altDown=false;
}

// Create a cookie.
function createCookie(name,value,days){
  var date = new Date();
  date.setTime(date.getTime()+(days*24*60*60*1000));
  document.cookie = name+"="+value+"; expires="+date.toGMTString()+"; path=/";
}

// Read a cookie.
function readCookie(name){
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

// Erase a cookie.
function eraseCookie(name){
	createCookie(name,"",-1);
}

// Get salt.
function getsalt(){
  el("Login").value="Please wait.";
  xmlHttp=newxmlrequest();
  xmlHttp.onreadystatechange=hashpw;
  var url="http://www.boardgame-online.com/salt.php?u="+el("l_loginname").value+"&r="+new Date().getTime();
  xmlHttp.open("GET",url,true);
  xmlHttp.send(null);
}

// Get award XML.
function getAwardXML(){
  xmlHttp=newxmlrequest();
  xmlHttp.onreadystatechange=parseAwardXML;
  var url="http://www.boardgame-online.com/awardsXML.php?u="+el("userid").value;
  xmlHttp.open("GET",url,true);
  xmlHttp.send(null);
}

function hashpw(){
  if(xmlHttp.readyState==4){
    el("Login").value="Please wait...";
    var userid=-1; var salt=-1;	var nonce=-1;

    var xml=xmlHttp.responseXML.getElementsByTagName("x")[0];
    for(var i=0;i<xml.childNodes.length;i++){
      var x=xml.childNodes[i];
      switch(x.nodeName){
        case "id":
        	userid=x.childNodes[0].nodeValue;
        	break;
        case "salt":
        	salt=x.childNodes[0].nodeValue;
        	break;
        case "nonce":
        	nonce=x.childNodes[0].nodeValue;
        	break;
        case "error":
        	alert(x.childNodes[0].nodeValue);
        	return;
      }
    }
    var pwsalt=RMDstring(salt+el("l_password").value);

    if(el("l_remember").checked){
      createCookie("un",el("l_loginname").value,60);
      createCookie("ph",pwsalt,60);
    }

		$("#l_salt").val(salt);
		$("#l_nonce").val(nonce);
		$("#l_pwhash").val(RMDstring(nonce+pwsalt));
		
		$("#l_password").val("");
		$("#loginform").submit();
		
		//old code
    //el("l_salt").value=salt;
    //el("l_nonce").value=nonce;
    //el("l_pwhash").value=RMDstring(nonce+pwsalt);
    
    //el("l_password").value="";
    //el("loginform").submit();
  }
}

function register(){
  if (el("password1").value==el("password2").value){
    var salt=Math.floor(Math.random()*899998)+100001;
    el("salt").value=salt;

    var newpwsalt=RMDstring(salt+el("password1").value);
    el("pwhash").value=newpwsalt;
    
    el("password1").value="";
    el("password2").value="";

    el("registerform").submit();
  }
  else{
    el("password1").value="";
    el("password2").value="";
    el("registerdiv").innerHTML="The passwords don't match.";
  }
}

function hashpwchange(){
  if (el("passwordnew").value.length<8){
    el("passwordnew").value="";
    el("passwordnew2").value="";
    el("changepwdiv").innerHTML="That's a bit too short for a password.";
  }
  else if (el("passwordnew").value==el("passwordnew2").value){
    var pwsalt=RMDstring(el("salt").value+el("password").value);
  
    el("pwhash").value=RMDstring(el("nonce").value+pwsalt);
    el("password").value="";
  
    var salt=Math.floor(Math.random()*899998)+100001;
    el("salt").value=salt;

    var newpwsalt=RMDstring(salt+el("passwordnew").value);
    el("pwhashnew").value=newpwsalt;
    
    el("passwordnew").value="";
    el("passwordnew2").value="";

    el("changepwform").submit();
  }
  else{
    el("passwordnew").value="";
    el("passwordnew2").value="";
    el("changepwdiv").innerHTML="The new passwords don't match.";
  }
}

function hashpwlost(){
  if (el("passwordnew").value==el("passwordnew2").value){
    var salt=Math.floor(Math.random()*899998)+100001;
    el("salt").value=salt;

    var newpwsalt=RMDstring(salt+el("passwordnew").value);
    el("pwhashnew").value=newpwsalt;
    
    el("passwordnew").value="";
    el("passwordnew2").value="";

    el("pwlostform").submit();
  }
  else{
    el("passwordnew").value="";
    el("passwordnew2").value="";
    el("lostpwdiv").innerHTML="The new passwords don't match.";
  }
}

function switchMode(){
  var txt=el("switchModeButton").innerHTML;
  el("switchModeButton").innerHTML=el("buttonText").innerHTML;
  el("buttonText").innerHTML=txt;
  
  for(var i=1; i<=4; i++){
    var table=el("records"+i);
    var records=table.getElementsByTagName('tr');
    
    for(var j=1; j<records.length; j++){
      txt=records[j].firstChild.innerHTML;
      records[j].firstChild.innerHTML=records[j].title;
      records[j].title=txt;
    }
  }
}


/********/
/* Chat */
/********/

// Adds text to the chat input field and focuses it. (Used for emoticon clicking.)
function c(s){
  if(!el("chatInput").disabled){
    el("chatInput").value+=s;
    el("chatInput").focus();
  }
}

// Handles server response.
function updatecallback(responseXML,aStatus){
  if(aStatus=="success"){
    // Get the root.
    xmlDoc=responseXML.getElementsByTagName("x")[0];
    
    if(xmlDoc==null)
      return;
    
    for(var inode_counter=0;inode_counter<xmlDoc.childNodes.length;inode_counter++){
      var x=xmlDoc.childNodes[inode_counter];
  	  try{
        switch(x.nodeName){
          case "c": // New chat message.
            // Check if this chatter is muted.
            var id = parseInt(x.getAttribute("id"));
            var i = getChatterID2(id);
            if(i>-1 && i in chatters && chatters[i].muted){
              return;
            }
            
            var time=parseInt(x.getAttribute("t"));
            var newDate=new Date();
            newDate.setTime(time*1000);
            hours=newDate.getHours();
            minutes=newDate.getMinutes();
            if(hours<10) hours="0"+hours;
            if(minutes<10) minutes="0"+minutes;
            
            soundParsed=false;
            
            targetName="";
            if(x.getAttribute("target"))
              targetName=x.getAttribute("target");
            
            var chatText=x.childNodes[0].nodeValue;
            chatText=parseSlash(chatText);
            chatText=parseChat(chatText);
            if( chatText.indexOf("</a>")==-1 && chatText.indexOf("<img ")==-1 )
              chatText=breakLongWords(chatText,40);
            
						// For DefectiveTurret.
						var defectiveIndex = chatText.indexOf(">DefectiveTurret<");
						if(defectiveIndex!=-1){
							chatText = chatText.substr(0,defectiveIndex)+" id='DefectiveTurret'"+chatText.substr(defectiveIndex)
						}
						
            // For Internet Explorer. Sigh.
            chatText = chatText.replace("&apos;","'");
						
            chat("("+hours+":"+minutes+") "+chatText);
						
						// For DefectiveTurret.
						if(defectiveIndex!=-1){
							$("#DefectiveTurret").attr("id","none").css("cursor","pointer").click(function(){
								playSound("defective_turret");
							}).attr("title","This turret is defective. Dispose of it.");
						}
            
            if(!soundParsed){
              var sound=parseInt(x.getAttribute("s"));
              switch(sound){
                case 1:
                  if(soundGame && soundOn)
                    soundGame.play();
                  break;
                case 2:
                  if(soundChat && soundOn)
                    soundChat.play();
                  break;
              }
            }
            break;
          case "gc": // Clear the open and running games lists.
            el("openPane").innerHTML="<span class='chat''><b>Open games:</b><br /></span>";
            el("runningPane").innerHTML="<span class='chat''><b>Running games:</b><br /></span>";
            numOpen=0;
            numRunning=0;
            break;
          case "gd": // Game started.
            var gid=x.getAttribute("id");
            var pane=el("openPane");
            if( el("openGame"+gid) )
              pane.removeChild( el("openGame"+gid) );
            var pane=el("runningPane");
            if( el("runningGame"+gid) )
              pane.removeChild( el("runningGame"+gid) );
            break;
          case "gn": // Number of players in a game changed.
            var gid=x.getAttribute("id");
            var num=x.getAttribute("n");
            if( el("oNum"+gid) )
              el("oNum"+gid).innerHTML="("+num+")";
            if( el("rNum"+gid) )
              el("rNum"+gid).innerHTML="("+num+")";
            break;
          case "go": // New open game.
            var gname=breakLongWords(x.childNodes[0].nodeValue,15);
            var gid=x.getAttribute("id");
            var creator=x.getAttribute("c");
            var finish=x.getAttribute("f");
            var mode=x.getAttribute("m");
            var modeClass="";
            if( (mode&1)==1 )
              modeClass+=" private";
            if( (mode&2)==2 )
              modeClass+=" team";
            var pane=el("openPane");
            if( !el("openGame"+gid) )
              pane.innerHTML+="<span class='chat' id='openGame"+gid+"'><a class='"+modeClass+"' href='g/game.php?g="+gid+"' target='_blank' title='Game by "+creator+". Finish: "+finish+"'>"+gname+" <b id='oNum"+gid+"'>(1)</b></a><br /></span>";
            break;
          case "gr": // New running game.
            var gname=breakLongWords(x.childNodes[0].nodeValue,15);
            var gid=x.getAttribute("id");
            var num=x.getAttribute("n");
            var creator=x.getAttribute("c");
            var finish=x.getAttribute("f");
            var mode=x.getAttribute("m");
            var modeClass="";
            if( (mode&1)==1 )
              modeClass+=" private";
            if( (mode&2)==2 )
              modeClass+=" team";
            var pane=el("runningPane");
            if( !el("runningGame"+gid) )
              pane.innerHTML+="<span class='chat' id='runningGame"+gid+"'><a class='"+modeClass+"' href='g/game.php?g="+gid+"' target='_blank' title='Game by "+creator+". Finish: "+finish+"'>"+gname+" <b id='rNum"+gid+"'>("+num+")</b></a><br /></span>";
            break;
        	case "i": // Last update counter. 
        	  if(lastUpdate>=parseInt(x.childNodes[0].nodeValue))
        	    return;
            lastUpdate=parseInt(x.childNodes[0].nodeValue);
            break;
        	case "j": // Video tag.
            // Check if this chatter is muted.
            var id = parseInt(x.getAttribute("id"));
            var i = getChatterID2(id);
            if(i>-1 && i in chatters && chatters[i].muted){
              return;
            }
            
            var movieID=x.childNodes[0].nodeValue;
            var length=parseInt(x.getAttribute("l"));
            currentSongID=parseInt(x.getAttribute("i"));
            loadMovie(movieID);
            break;
          case "m": // Plain message.
            var msg=x.childNodes[0].nodeValue;
            if( msg.indexOf("</a>")==-1 && msg.indexOf("<img ")==-1 )
              msg=breakLongWords(msg,40);
            chat(msg);
            break;
          case "no": // Number of open games.
            $("#numOpen").text(x.childNodes[0].nodeValue);
            break;
          case "np": // Number of players.
            $("#numPlayers").text(x.childNodes[0].nodeValue);
            break;
          case "npro": // Number private open games.
            var numPrivate = x.childNodes[0].nodeValue;
						var s = numPrivate==1 ? "" : "s";
						if(numPrivate>0)
							$("#openPane").append("<span>"+numPrivate+" private game"+s+".<br /></span>");
            break;
          case "nprr": // Number private running games.
            var numPrivate = x.childNodes[0].nodeValue;
						var s = numPrivate==1 ? "" : "s";
            if(numPrivate>0)
							$("#runningPane").append("<span>"+numPrivate+" private game"+s+".<br /></span>");
            break;
          case "nr": // Number of running games.
            $("#numRunning").text(x.childNodes[0].nodeValue);
            break;
					case "st": // Status change.
            id=parseInt(x.getAttribute("id"));
						var cStatus=x.childNodes[0].nodeValue;
						statusUpdate(id,cStatus);
            break;
          case "u": // Chatter enters or leaves.
            id=parseInt(x.getAttribute("id"));
            if(id>0){ // Chatter enters.
              var name=x.childNodes[0].nodeValue;
              var priv=x.getAttribute("pr");
              var don=x.getAttribute("d");
							var cStatus = x.getAttribute("st");
              if(cStatus!=1)
								addChatter(id,name,priv,don,cStatus);
            }
            else{ // Chatter leaves.
              id*=-1;
              removeChatter(id);
            }
            break;
          default:
            //chat("Unknown XML tag from server: "+x.nodeName);
        }
	    }
      catch(err)
      {
        // Crappy way to detect a Flash error with Sound Manager 2.
        if( err.toString().indexOf("_s.o._")!=-1 || err.toString().indexOf("snd.")!=-1 ){
          if(!flashIsBugged){
            chat("<b style='color: red;'>ERROR: Your Flash plugin has bugged. Restart your browser to re-enable sounds.</b>");
            flashIsBugged=true;
          }
        }
        else{
		      chat("JavaScript Error on line "+err.lineNumber+": "+err.toString());
		    }
		  }
    }
  }
}

// Find words that are too long in a string. Break them up if necessary.
function breakLongWords(aStr,aBreakLength){
  var words = aStr.split(" ");
  var brokenString="";
  for(var i=0; i<words.length; i++){
    while(words[i].length>aBreakLength){
      var part = words[i].substr(0,aBreakLength);
      brokenString+=part+" ";
      words[i] = words[i].substr(aBreakLength);
    }
    brokenString+=words[i]+" ";
  }
  return brokenString;
	//return aStr;
}

// A player enters the chat.
function addChatter(id,name,privileges,donated,cStatus){
	if(id==myId)
		status=cStatus;
	
	// Make sure we don't get doubles.
  for(var i=0; i<chatters.length; i++){
    if(chatters[i].id==id)
      return;
  }
  
  var style="";
  var title="";
  if((privileges&524288)==524288){
    type="admin";
    style="admin";
    title=name+" is a full admin. Beware their wrath!";
  }
  else if((privileges&16384)==16384){
    type="admin";
    style="artist";
    title=name+" is an artist admin. Thank them for all our amazing art!";
  }
  else if((privileges&131072)==131072){
    type="normal";
    style="juke";
    title=name+" is a jukebox admin. Beware their funk!";
  }
  else if(donated>=100){
    type="donator";
    style="donator";
    title=name+" donated "+(donated/100).toFixed(2)+" euro. What a hero!";
  }
  else{
    type="normal";
    style="user";
    title=name+" is a basic player.";
  }
  
  chatters[numChatters]=new Object();
  chatters[numChatters].id=id;
  chatters[numChatters].name=name;
  chatters[numChatters].privileges=privileges;
  chatters[numChatters].donated=donated;
  chatters[numChatters].muted=false;
  numChatters++;
  $("#numMembers").text(numChatters);
  
	//status
	statusImage="";
	if(cStatus==2)
		statusImage="<img src='images/icons/clock.png' id='afkIcon"+id+"' title='This user is afk.'/>";
	if(cStatus==3)
		statusImage="<img src='images/icons/exclamation.png' id='lfgIcon"+id+"' title='This user wants to play a game.'/>";
	
  var html="<span class='chat' id='chatter"+id+"' title='"+title+"'><a class='"+style+"' href='user.php?user="+id+"' target='_blank'>"+name+" "+statusImage+"</a></span>";
  
  // Add chatter alphabetically to the div of the right type.
  chatterAdded=false;
  $("#"+type+"sPane>span").each( function(index){
    if( !chatterAdded && $(this).text().toUpperCase()>name.toUpperCase() ){
      $(this).before(html);
      chatterAdded=true;
    }
  });
  if(!chatterAdded){
    $("#"+type+"sPane").append(html);
  }
}

// A player leaves the chat.
function removeChatter(id){
  for(var i=0; i<chatters.length; i++){
    if(chatters[i].id==id){
      chatters.splice(i,1);
      numChatters--;
      $("#chatter"+id).remove();
      break;
    }
  }
  $("#numMembers").text(numChatters);
}

function statusUpdate(id, cStatus){
	if ($("#chatter"+id).length==0)
	{
		return;
	}
	if(cStatus==2)//change to afk
	{
		if( $("#lfgIcon"+id).length!=0 )//first remove lfg-icon if its there
		{
			$("#lfgIcon"+id).remove();
		}
		if( $("#afkIcon"+id).length==0 )
		{
			var htmlString = $("#chatter"+id).html();
			htmlString = htmlString.replace("</a>"," <img src='images/icons/clock.png' id='afkIcon"+id+"' title='This user is afk.'/></a>");
			$("#chatter"+id).html(htmlString);
		}
	}
	else if (cStatus==3)//change to lfg 
	{
		if( $("#afkIcon"+id).length!=0 )//first remove afk-icon if its there
		{
			$("#afkIcon"+id).remove();
		}
		if( $("#lfgIcon"+id).length==0 )
		{
			var htmlString = $("#chatter"+id).html();
			htmlString = htmlString.replace("</a>"," <img src='images/icons/exclamation.png' id='lfgIcon"+id+"' title='This user wants to play a game.'/></a>");
			$("#chatter"+id).html(htmlString);
		}
	}
	else if (cStatus==0) //remove afk icon
	{
		if( $("#afkIcon"+id).length!=0 )
		{
			$("#afkIcon"+id).remove();
		}
		if( $("#lfgIcon"+id).length!=0 )
		{
			$("#lfgIcon"+id).remove();
		}
	}
}

// Send a chat message to the server.
function sendChat(aMessage){
  // Flood prevention system.
  if(floodCounterFive>=FLOOD_CAP_FIVE){
    chat("<b>Flood prevention! You cannot send more than 3 messages per 5 seconds!</b>");
    return;
  }
  /*if(floodCounterTen>=FLOOD_CAP_TEN){
    chat("<b>Flood prevention! You cannot send more than 5 messages per 10 seconds!</b>");
    return;
  }*/
  if(floodCounterMinute>=FLOOD_CAP_MINUTE){
    chat("<b>Flood prevention! You cannot send more than 15 messages per minute!</b>");
    return;
  }
  floodCounterFive++;
  floodCounterTen++;
  floodCounterMinute++;
  
  // Get the message.
  if(aMessage){
    var str = aMessage;
  }
  else{
    var str=el("chatInput").value;
    el("chatInput").value="";
  }
  
	var statusChanged = false;
	if(status==2){ // Make player go off from afk if they use the chat, except when searching for songs.
		statusChanged=true;
		changeStatus(0);
	}
	
  for(var i=0;i<str.length;i++){
    if(str[0]==" "){
      str=str.slice(1);
      i--;
    }
    else if(str[0]=="/"){
      if(str=="/joke")
        str = "/me tells a joke: "+random_joke();
      if(str=="/pickup")
        str = "/me uses a pickup line: "+random_pickup();
      
      if( str.search("ignore ")==1 || str.search("squelch ")==1 || str.search("mute ")==1 ){
        str = str.substr( str.search(" ")+1 );
        muteChatter(str);
        return;
      }
      
      var url="";
      if( str.search("image")==1 || str.search("img")==1 ){
        url="chatImage";
        str=cutSpace(str);
      }
      else if( str.search("link")==1 || str.search("url")==1 ){
        url="chatLink";
        str=cutSpace(str);
      }
      else if( str.search("random")==1 || str.search("roll")==1 || str.search("rand")==1 ){
        url="chatRoll";
        str=cutSpace(str);
      }
      else if( str.search("jukefind ")==1 || str.search("jf ")==1 ){
        if( str.search("jukefind ")==1 )
          str=str.substr(9);
        else // str.search("jf ")==1 
          str=str.substr(3);
				searchForSongs(str);
				return;
      }
      else if( str.search("video ")==1 || str.search("movie ")==1 ){
        url="chatVideo";
        if(str.length>6)
          str=str.substr(6);
        else
          return;
      }
      else if( str.search("me ")==1 ){
        url="chatMe";
        if(str.length>3)
          str=str.substr(3);
        else
          return;
      }
      else if( str.search("item ")==1 ){
        url="chatItem";
        if(str.length>5)
          str=str.substr(5);
        else
          return;
      }
			else if( str.search("afk")==1 ){
        if(!statusChanged)
				{
					if(status!=2)
						changeStatus(2);
					else
						changeStatus(0);
				}
        return;
      }
			else if( str.search("lfg")==1 || str.search("game")==1 || str.search("play")==1 ){
        if(status!=3)
					changeStatus(3);
				else
				{	
					changeStatus(0);
					chat("<b>Status changed back to normal.</b>");
					return;
				}
      }
			else if( str.search("normal")==1 ){
        if(status!=0)
				{
					changeStatus(0);
					chat("<b>Status changed to normal.</b>");
					return;
				}
      }
			else if( str.search("poof")==1 || str.search("disappear")==1 ){
        if(status!=1)
					changeStatus(1);
      }
      
      if(url!=""){
        //str=strEncode(str);
        str=encodeURIComponent(str);
        request(url+=".php?p="+myId+"&i="+lastUpdate,"c="+str);
        return;
      }
      
      switch(str){
        case "/crazy":
          if(isCrazy){
            isCrazy=false;
            str+="Off";
          }
          else{
            isCrazy=true;
          }
          break;
        case "/pirate":
          if(isPirate && !isPirateDay){
            isPirate=false;
            str+="Off";
          }
          else{
            isPirate=true;
          }
          break;
        case "/stoned":
          if(isStoned){
            isStoned=false;
            str+="Off";
          }
          else{
            isStoned=true;
          }
          break;
        case "/drunk":
          if(isDrunk){
            isDrunk=false;
            str+="Off";
          }
          else{
            isDrunk=true;
          }
          break;
        case "/asian":
          if(isAsian){
            isAsian=false;
            str+="Off";
          }
          else{
            isAsian=true;
          }
          break;
        case "/caps":
        case "/CAPS":
          if(isCAPS){
            isCAPS=false;
            str+="Off";
          }
          else{
            isCAPS=true;
          }
          break;
        case "/help":
          chat("<b>List of chat options:</b>");
          chat("<b>/me</b> [some text]");
          chat("<b>/roll</b> (also try: /roll 500 or /roll 50 500)");
          chat("<b>/link</b> [a link]");
					chat("<b>Change status:</b>");
					chat("<b>/afk</b> to go Away From Keyboard.");
					chat("<b>/game</b> to show that you want to join a game.");
          chat("<b>Emotes:</b>");
          chat("<b>/fart</b> or /fart [start of someone's name]");
          chat("For example, try /burp [first letter(s) of your name]");
          chat("<b>/item</b> [part of item name] to link a board game item.");
          chat("<b>/video</b> [youtube link] to share a youtube video with everyone in the chat.");
          chat("<b>/mute</b> [start of someone's name] to mute/unmute another chatter.");
          return;
      }
      break;
    }
    else{
      break;
    }
  }
  
  var isVideo=false;
  if( str.indexOf("http://www.youtube.com/watch?v=")!=-1 ){
    var pos = str.indexOf("http://www.youtube.com/watch?v=");
    var videoLink = str.substr(pos,42);
    isVideo=true;
  }
  
  if(str[0]!="/"){
    if(str=="")
      return;
    if(isCrazy)
      str=makeCrazy(str);
    if(isPirate || isPirateDay)
      str=makePirate(str);
    if(isStoned)
      str=makeStoned(str);
    if(isDrunk)
      str=makeDrunk(str);
    if(isAsian)
      str=makeAsian(str);
    if(isCAPS)
      str=makeCAPS(str);
  }
  
  //str=strEncode(str);
  str=encodeURIComponent(str);
  
  request("chat.php?p="+myId+"&i="+lastUpdate,"c="+str);
  if(isVideo){
    request("chatVideo.php?p="+myId+"&i="+lastUpdate,"c="+videoLink);
  }
}

function searchForSongs(search){
	search=encodeURIComponent(search);
  request("chatJukefind.php?p="+myId+"&i="+lastUpdate,"c="+search);
}

// Asks the server if there are chat updates.
function updateChat(){
  request("updateChat.php?i="+lastUpdate,null);
}

// Tells the server you have entered the chat.
function enterChat(){
  request("enterChat.php?i="+lastUpdate,null);
}

// Tells the server you are leaving the chat.
function leaveChat(){
  request("leaveChat.php?i="+lastUpdate,null);
}

// Tell the server you are still in the chat.
function chatCheck(){
  request("chatCheck.php?i="+lastUpdate,null);
  //chat("chatCheck performed.");
}

// Ask the server for updated information about current games.
function updateGames(){
  request("updateGames.php?i="+lastUpdate,null);
}

// Change your status.
function changeStatus(newStatus){
  request("chatStatus.php?p="+myId+"&st="+newStatus,null);
	status = newStatus;
}

function toggleInvisible() {
	if(status!=1)
	{
		changeStatus(1);
		chat("<b>You are now invisible.</b>");
	}
	else
	{
		changeStatus(0);
		chat("<b>You are now visible again.</b>");
	}
}

// Send a request to the server.
function request(script,toSend){
  $.ajax({
    url: script,
    type: "post",
    dataType : "xml",
    data: toSend,
    cache: false,
    success: updatecallback
  });
}

// Encode a string to escape certain evil characters.
function strEncode(str){
  str=str.replace(/%/,"%25");
  str=str.replace(/#/,"%23");
  str=str.replace(/\+/,"%2B");
  str=str.replace(/&/,"%26");
  str=str.replace(/\//,"%2F");
  str=str.replace(/=/,"%3D");
  return str;
}

// Cut everything up till and including the first space from a string and return the rest.
function cutSpace(str){
  if( str.search(" ")>-1 )
    return str.substr( str.search(" ")+1 );
  else
    return "";
}

// Return a 'random' number to keep the randomness of different players synced. (Syncing is not 100% reliable atm.)
function random(max){
  if (seed==1)
    seed=3453;
  seed=(seed*seed)%45491;
  return seed%(max+1);
}

// Formats chat text to be drunk.
function makeDrunk(txt){
  txt=txt.replace(/s/g,"sh");
  txt=txt.replace(/S/g,"SH");
  
  do
  {
    txt=txt.replace(/Shs/g,"Ss");
    txt=txt.replace(/shs/g,"ss");
    txt=txt.replace(/shS/g,"sS");
    txt=txt.replace(/ShS/g,"SS");
  } while(txt.indexOf("Shs")>-1 || txt.indexOf("shs")>-1 || txt.indexOf("shS")>-1 || txt.indexOf("ShS")>-1);
 
  if(Math.random()>0.5)
    txt+=" ...hic!";
  
  return txt;
}

// Formats chat text to be piratey.
function makePirate(txt){
  txt=txt.replace(/ar/g,"arrrrr");
  txt=txt.replace(/AR/g,"ARRRRRR");
  txt=txt.replace(/aR/g,"aRRRRRR");
  txt=txt.replace(/Ar/g,"Arrrrr");
  txt=txt.replace(/ my /g," me ");
  txt=txt.replace(/My /g,"Me ");
  txt=txt.replace(/ am /g," be ");
  txt=txt.replace(/Am /g,"Be ");
  txt=txt.replace(/ is /g," be ");
  txt=txt.replace(/Is /g,"Be ");
  txt=txt.replace(/hello/g,"ahoy");
  txt=txt.replace(/Hello/g,"Ahoy");
  txt=txt.replace(/friend/g,"matey");
  txt=txt.replace(/Friend/g,"Matey");
  txt=txt.replace(/hi /g,"ahoy ");
  txt=txt.replace(/Hi /g,"Ahoy ");
  txt=txt.replace(/hey/g,"ahoy");
  txt=txt.replace(/Hey/g,"Ahoy");
  txt=txt.replace(/guys/g,"me hearrrrrrties");
  txt=txt.replace(/Guys/g,"Me hearrrrrrties");
  
  var rand=Math.random();
  if(rand<=0.1)
    txt+=" Arrrr, matey!";
  else if(rand<=0.2)
    txt="Shiver me timbers! "+txt;
  else if(rand<=0.3)
    txt="Avast! "+txt;
  else if(rand<=0.4)
    txt+=" Yarrrrr!";
  return txt;
}

// Formats chat text to be stoned.
function makeStoned(txt){
  var rand=Math.random();
  if(rand<=0.08)
    txt+=" Yeah, dude...";
  else if(rand<=0.16)
    txt="Woah! "+txt;
  else if(rand<=0.24)
    txt="Duuuuuude! "+txt;
  else if(rand<=0.32)
    txt+=" I'm way out there, man!";
  else if(rand<=0.40)
    txt+=" Hehehehehehehehehe.";
  else if(rand<=0.48)
    txt="Wuh... what? "+txt+" Oooooh! Hehe!";
  else if(rand<=0.56)
    txt+=" Funky colors, man!";
  
  return txt;
}

// Formats chat text to be crazy.
function makeCrazy(txt){
  var arr=new Array("Bananas are blue!","4 8 15 16 23 42","Woop woop!","Oink!","I'm made of yellow!","Backa lacka dacka!","Burka durka durk!",
        "Oh, we're never gonna surviiiiiiive... unless... we get a little craaaaazy!","The ducks will reign supreme!","Anyone feel like a humpy?",
        "No! YOU are the boob!","IMMA CHARGIN MAH LAZERS!","Titty biscuits!","I'm a little piggy! This is my snout! Oink oink oink!",
        "In Soviet Russia, crazy are YOU!","The goggles! They do nothing!","Got milk?","Crazy person is crazy.","Did everything taste purple just now?",
        "Carebears are real!","Wonkers!","You all saw it! That orphanage attacked ME!");
  txt=arr[random(21)];
  
  return txt;
}

// Formats chat text to be asian.
function makeAsian(txt){
  txt=txt.replace(/l/g,"r");
  txt=txt.replace(/L/g,"R");
  
  return txt;
}

// Formats chat text to be in CAPS.
function makeCAPS(txt){
  txt=txt.toUpperCase();
  
  return txt;
}

// Parses slash commands for the site chat.
function parseSlash(s){
  // Target name.
  var ind_t=s.indexOf("<t>");
  while(ind_t>-1)
  {
    s=s.replace(/<t>/,targetName);
    ind_t=s.indexOf("<t>");
  }
  
  // Sound
  var ind_j=s.indexOf("<j>");
  while(ind_j>-1)
  {
    var id=0;
    var length=0;
    var ind_j2=s.indexOf("</j>");
    if(ind_j2>-1)
    {
      length=ind_j2-ind_j-3;
      if(length>0)
      {
        id=s.substr(ind_j+3,length);
      }
      s=s.substring(0,ind_j)+s.substring(ind_j2+4);
    }
    playSound(id);
    ind_j=s.indexOf("<j>");
    soundParsed=true;
  }
  
  return s;
}

// Parses slash commands for the list of slash commands.
function parseCommand(s){
  // Target name.
  var ind_t=s.indexOf("<t>");
  while(ind_t>-1)
  {
    s=s.replace(/<t>/,"&lt;target&gt;");
    ind_t=s.indexOf("<t>");
  }
  
  // Sound tag.
  var ind_j=s.indexOf("<j>");
  while(ind_j>-1)
  {
    var ind_j2=s.indexOf("</j>");
    if(ind_j2>-1)
    {
      s=s.substring(0,ind_j)+s.substring(ind_j2+4);
    }
    ind_j=s.indexOf("<j>");
    s = "<b>"+s+"</b>";
  }
  
  return s;
}

// Play a sound.
function playSound(id){
  if(!soundOn || soundManager==null)
    return;
  
  var snd=soundManager.getSoundById(id);
  if(snd!=null)
  {
    snd.play();
  }
  else
  {
    snd=soundManager.createSound(id,'audio/'+id+'.mp3');
    soundManager.setVolume(id,volume);
    if(snd!=null)
    {
      extraSounds[extraSounds.length]=id;
      snd.play();
    }
  }
}

// Toggle sound.
function toggleSound(){
  if(soundChat==null || soundOn)
  {
    el("soundToggle").src="images/soundOff_small.png";
    soundOn=false;
  }
  else
  {
    el("soundToggle").src="images/soundOn_small.png";
    soundOn=true;
  }
}

// Activate an item tooltip.
function activateTooltip(tooltip, element){
  if(!el(element))
    return;
  if(tooltip!="")
    el(element).title=tooltip;
  if(browser == "Microsoft Internet Explorer")
  {
    $("#"+element).tooltip({
    	track: true,
    	delay: 0,
    	showURL: false,
    	showBody: " - ",
    	extraClass: "prettyIE",
    	fixPNG: true,
    	top: -88,
    	left: -270
    });
  }
  else
  {
    $("#"+element).tooltip({
    	track: true,
    	delay: 0,
    	showURL: false,
    	showBody: " - ",
    	extraClass: "pretty",
    	fixPNG: true,
    	top: -88,
    	left: -260
    });
  }
}

// Fix tooltips on in the item table.
function parseTooltip(s){
  var ind=s.indexOf(" - ");
  if(ind>-1)
  {
    s=s.replace(/ - /,"</h3>");
  }
  s="<h3>"+s;
  return s;
}

// Parse chat text to add emoticons in.
function parseChat(s){
  for(var i in icons){
    var ind;
    while(true){
      ind=( s.toLowerCase() ).indexOf( i.toLowerCase() );
      if(ind>-1)
        s=s.slice(0,ind)+"<img src='images/icons/"+icons[i]+".png' />"+s.slice(ind + i.length);
      else
        break;
    }
  }
  return s;
}

// A movie link has been clicked in the chat.
function movieClick(link,id,title,length){
  if(shiftDown || ctrlDown || altDown){
    queueMovie(id,link,title,length);
  }
  else{
    loadMovie(link);
    currentSongID=id;
  }
}

// Fires when the YouTube player is ready.
function onYouTubePlayerReady(playerId) {
  myjukebox.addEventListener("onStateChange", "youTubePlayerStateChanged");
  myjukebox.addEventListener("onError", "youTubePlayerErrorFired");
	jukeboxLoaded = true;
	setInterval(timeChanged,500);
}

function youTubePlayerStateChanged(newState)
{
  switch(newState)
  {
    case STATE_UNSTARTED:
      //...
      break;
    
    case STATE_ENDED:
      var songEnded = true;
      if(!autoPlay)
        return;
      if(!loadingNextSong){
        loadingNextSong = true;
        nextSong();
      }
      break;
    
    case STATE_PLAYING:
      //...
      break;
    
    case STATE_PAUSED:
      //...
      break;
    
    case STATE_BUFFERING:
      //...
      break;
    
    case STATE_VIDEO_CUED:
      //...
      break;
    
    default:
      // Error state. This should never happen!
      break;
  }
}

function youTubePlayerErrorFired(error){
  songEnded = true;
  if(error==2 || error==100) // Wrong link or removed by user are the only safe detections.
    flag();
  if(autoPlay){
    loadingNextSong = true;
    youTubeErrorNextSongHandle = setTimeout(nextSong,5000);
  }
}

// Function is called very often to check the time and fire events.
function timeChanged(){
  if(!autoPlay)
    return;
  var time = myjukebox.getCurrentTime();
  if(time>songLength){
    if(!loadingNextSong){
      loadingNextSong = true;
      songEnded = true;
      nextSong();
    }
  }
  else{
    loadingNextSong = false;
  }
}

// Load a YouTube movie below the chat.
function loadMovie(link){
  songLength=parseInt($("#"+link).attr("name"));
  clearTimeout(youTubeErrorNextSongHandle);
	if(jukeboxLoaded){
		myjukebox.loadVideoById(link);
	}
	else{
		$("#jukediv").css("visibility","visible");
		$("#jukediv").css("border","2px solid #CCCCCC");
  	var params = { allowScriptAccess: "always" };
    var atts = { id: "myjukebox" };
    swfobject.embedSWF("http://www.youtube.com/v/"+link+"?enablejsapi=1&playerapiid=jukebox&autoplay=1&version=3",
                       "jukebox", "425", "344", "8", null, null, params, atts);
  }
  loadingNextSong = false;
  songEnded = false;
}

// Appends a Youtube movie to the playlist queue.
function queueMovie(id,link,title,length){
  if( el('playlistdiv').getElementsByTagName('p').length==0 )
    el('playlistdiv').style.display="block";
  el('playlistdiv').innerHTML+="<span id='playlist"+numMoviesInPlaylist+"'><img name='"+numMoviesInPlaylist+"' style='cursor: pointer;' alt='Remove from playlist.' title='Remove from playlist.' src='images/icons/remove.png' onclick='dequeueMovie(this.name);' /> <a style='cursor: pointer; color:#0000A0;' onclick='playlistClick(\""+link+"\",( this.parentNode.getElementsByTagName(\"img\")[0].name ),"+id+");' alt='Play this song.' title='Play this song.' id='"+link+"' name='"+id+"'>"+title+"</a><br /></span>";
  
  numMoviesInPlaylist++;
}

// Removes a Youtube movie from the playlist queue.
function dequeueMovie(index){
  index = parseInt(index);
  el('playlistdiv').removeChild( el('playlist'+index) );
  numMoviesInPlaylist--;
  if(numMoviesInPlaylist==0)
    el('playlistdiv').style.display="none";
  var i=index+1;
  while( el('playlist'+i) )
  {
    el('playlist'+i).getElementsByTagName('img')[0].name=""+(i-1);
    el('playlist'+i).id='playlist'+(i-1);
    i++;
  }
}

// A playlist item has been clicked.
function playlistClick(link,index,id){
  if( el('playlist'+currentPlaylistSong) )
    el('playlist'+currentPlaylistSong).style.backgroundColor='#44CCFF';
  loadMovie(link);
  currentPlaylistSong=parseInt(index);
  if( el('playlist'+currentPlaylistSong) )
    el('playlist'+currentPlaylistSong).style.backgroundColor='#F9FAAA';
  currentSongID=id;
}

// Toggle autplay mode.
function toggleAutoplay(){
  if(autoPlay){
    autoPlay=false;
    chat("<b>Autoplay is now OFF!</b>");
  }
  else{
    autoPlay=true;
    chat("<b>Autoplay is now ON!</b>");
    if(!songEnded)
      return;
    if(numMoviesInPlaylist>0){
      if( el('playlist'+currentPlaylistSong) )
        el('playlist'+currentPlaylistSong).style.backgroundColor='#44CCFF';
      
      if(shuffleOn && numMoviesInPlaylist>1){
        var rand=0;
        do{
          rand = Math.floor(Math.random()*numMoviesInPlaylist);
        } while(rand==currentPlaylistSong);
        currentPlaylistSong=rand;
      }
      else if( el('playlist'+(currentPlaylistSong+1)) )
        currentPlaylistSong++;
      else
        currentPlaylistSong=0;
      el('playlist'+currentPlaylistSong).style.backgroundColor='#F9FAAA';
      loadMovie( el('playlist'+currentPlaylistSong).getElementsByTagName('a')[0].id );
      currentSongID=el('playlist'+currentPlaylistSong).getElementsByTagName('a')[0].name;
    }
    else{
      jukeRand();
    }
  }
}

function toggleShuffle(){
  if( shuffleOn ){
    shuffleOn=false;
    chat("<b>Playlist Shuffle is now OFF!</b>");
  }
  else{
    shuffleOn=true;
    chat("<b>Playlist Shuffle is now ON!</b>");
  }
}

// Play a new song in autoplay mode, either from the playlist or a random one from the server.
function nextSong(){
  if(!autoPlay)
    return;
  if(numMoviesInPlaylist>0){
    if( el('playlist'+currentPlaylistSong) )
      el('playlist'+currentPlaylistSong).style.backgroundColor='#44CCFF';
    
    if(shuffleOn && numMoviesInPlaylist>1){
      var rand=0;
      do{
        rand = Math.floor(Math.random()*numMoviesInPlaylist);
      } while(rand==currentPlaylistSong);
      currentPlaylistSong=rand;
    }
    else if( el('playlist'+(currentPlaylistSong+1)) )
      currentPlaylistSong++;
    else
      currentPlaylistSong=0;
    
    el('playlist'+currentPlaylistSong).style.backgroundColor='#F9FAAA';
    loadMovie( el('playlist'+currentPlaylistSong).getElementsByTagName('a')[0].id );
    currentSongID=el('playlist'+currentPlaylistSong).getElementsByTagName('a')[0].name;
  }
  else{
    jukeRand();
  }
}

// Request 10 random songs.
function jukeGenerate(){
  request("chatJukegenerate.php?p="+myId,null,true);
}

// Request a random song.
function jukeRand(){
  request("chatJukerandom.php?p="+myId,null,true);
}

// Share the currently playing song.
function shareSong(){
  // Flood prevention system.
  if(floodCounterFive>=FLOOD_CAP_FIVE){
    chat("<b>Flood prevention! You cannot send more than 3 messages per 5 seconds!</b>");
    return;
  }
  /*if(floodCounterTen>=FLOOD_CAP_TEN){
    chat("<b>Flood prevention! You cannot send more than 5 messages per 10 seconds!</b>");
    return;
  }*/
  if(floodCounterMinute>=FLOOD_CAP_MINUTE){
    chat("<b>Flood prevention! You cannot send more than 15 messages per minute!</b>");
    return;
  }
  floodCounterFive++;
  floodCounterTen++;
  floodCounterMinute++;
	
  if(currentSongID==-1){
    chat("Can't share music if you ain't playing any.");
    return;
  }
  request("chatJukeshare.php?p="+myId+"&i="+lastUpdate,"c="+currentSongID,true);
}

// Report that something is wrong with the currently playing song.
function flag(){
  if(currentSongID!=-1)
    request("jukeflag.php?p="+"&id="+currentSongID,null,true);
  else
    chat("Can't flag music if you ain't playing any.");
}

// Scrolls the scrollbar in the chat all the way down.
function scrl(){
	var chatPane = document.getElementById("chatPane");
	chatPane.scrollTop = chatPane.scrollHeight; 
	//$("#chatPane").append("Height: " + $("#chatPane").scrollTop() + " -  scrollTop: " + $("#chatPane").attr("scrollTop")+"<br />");
}

// Puts text in the chat.
function chat(txt){
	var scroll = haveToScroll();
  $("#chatPane").append("<span class='chat'>"+txt+"</span><br />");
	if(scroll)
		scrl();
}

function haveToScroll(){
	var scrollTop = $("#chatPane").scrollTop();
	var scrollHeight = $("#chatPane")[0].scrollHeight; 
	var height = $("#chatPane").height();
	return (scrollTop + height+1) > scrollHeight;
}

var jokes = [];
jokes.push("There's 10 kinds of people in the world. Those who understand binary and those who don't.");
jokes.push("Reality is for people who can't face Science Fiction.");
jokes.push("There's no future in time travel.");
jokes.push("Entropy isn't what it used to be.");
jokes.push("What does an old lady have between her tits that a young lady doesn't? Her belly button.");
jokes.push("How do you get your wife to scream while you are making love? Call her up and tell her what you're doing.");
jokes.push("What did the elephant say to the naked man? How do you eat with that thing?");
jokes.push("Hitler: \"My dog has no nose.\" Crowd: \"Then how does it smell?\" Hitler: \"Awful.\"");
jokes.push("Why do men always want to be on the bottom during sex? Because all they know is how to fuck up.");
jokes.push("Why should you keep a monkey in your pants? If your pants fall down you can pretend that everyone is laughing at the monkey.");
jokes.push("How is a condom like a Kodak print? They both capture that special moment.");
jokes.push("Why can't Santa have children? He only comes once a year.");
jokes.push("Why do women fake orgasms? They think men care.");
jokes.push("What is the best thing about a blow job? The five minutes of silence.");
jokes.push("Why do walruses go to Tupperware parties? To find a tight seal.");
jokes.push("Never wrestle a pig. You both get dirty, and he likes it.");
jokes.push("What does a blonde say after her doctor tells her that she's pregnant. \"Is it mine?\"");
jokes.push("Isn't it a bit unnerving that doctors call what they do 'practice'?");
jokes.push("A doctor is the only man who can tell a woman to take off all her clothes and then send a bill to her husband!");
jokes.push("Beauty is in the eye of the beer holder.");
jokes.push("Alcohol doesn't make you FAT... it makes you LEAN... against tables, chairs, floors, walls and ugly people!");
jokes.push("God must love stupid people; He made so many.");
jokes.push("Light travels faster than sound. This is why some people appear bright until you hear them speak.");
jokes.push("Yo momma so ugly, when she walks into a bank, they turn off the surveillence cameras.");
jokes.push("Yo momma so fat, when she fell in love she broke it.");
jokes.push("Yo momma so dumb, she brought a spoon to the Super-Bowl.");
jokes.push("How do we know the Indians were the first people in North America? They had reservations.");
jokes.push("Where does an Irish person go on a vacation? A new bar.");
jokes.push("How can you tell the difference between men's real gifts and their guilt gifts? Guilt gifts are nicer.");
jokes.push("Why was the math textbook so sad? He had a lot of problems!");

function random_joke(){
  return jokes[Math.floor(Math.random()*jokes.length)];
}

var pickups = [];
pickups.push("Are you going to harvest the rest of my organs? Because you just stole my heart.");
pickups.push("Hey babe, wanna make an easy fifty bucks?");
pickups.push("If I could make you come with just one finger, imagine what I could do with the rest of me.");
pickups.push("I lost my teddy bear, can I sleep with you instead?");
pickups.push("You have a lovely voice and I'm sure it would sound even better muffled by my penis.");
pickups.push("Hi. I'm an astronaut, and my next mission is to explore Uranus.");
pickups.push("If my pillow had a hole in it, I would name it after you.");
pickups.push("My penis died, could you give him mouth-to-mouth?");
pickups.push("My favorite word is sux because it's sex with you in it.");
pickups.push("If I flip this coin what are the chances of me getting head?");
pickups.push("Are you into furries?");
pickups.push("I don't like to be tied down, except for when I do.");
pickups.push("My love for you is like diarrhea. I can't hold it in.");
pickups.push("Nice legs, what time do they open?");
pickups.push("Are you a parking ticket? Cus you've got FINE written all over you.");
pickups.push("Are you an angel? Because I have a boner.");
pickups.push("If you were my shin I'd bang you on the coffee table.");
pickups.push("sup bitch");
pickups.push("Fuck me if I'm wrong, but is your name Gretchen?");
pickups.push("Good day for weather.");
pickups.push("If all men think with their dicks, would you care to blow my mind?");
pickups.push("Why don't you come sit on my lap, and we'll talk about the first thing that pops up.");
pickups.push("If I told you I was gay, would you let me touch you?");
pickups.push("You may fall from the sky, you may fall from a tree, but the best way to fall... is in love with me.");
pickups.push("Crap. Something is wrong with my cell phone. {Oh Really. What is that?} Its just that... your number's not in it.");
pickups.push("Do you believe in love at first sight, or should I walk by again?");
pickups.push("It's a good thing that I have my library card, because I am totally checking you out!");
pickups.push("If I received a nickel for everytime I saw someone as beautiful as you, I'd have five cents.");
pickups.push("Can I have your picture so I can show Santa what I want for Christmas?");
pickups.push("If you stood in front of a mirror and held up 11 roses, you would see 12 of the most beautiful things in the world.");
pickups.push("See my friend over there? He wants to know if you think I'm cute.");
pickups.push("Are those space pants? Because your ass is out of this world!");
pickups.push("My love for you is like diarrhea, I just can't hold it in!");

function random_pickup(){
  return pickups[Math.floor(Math.random()*pickups.length)];
}

function getChatterID(aName){
  for(var i=0; i<chatters.length; i++){
    if( chatters[i].name.toLowerCase().indexOf(aName.toLowerCase())==0 )
      return i;
  }
  return -1;
}

function getChatterID2(aID){
  for(var i=0; i<chatters.length; i++){
    if( chatters[i].id==aID )
      return i;
  }
  return -1;
}

function muteChatter(aName){
  var id = getChatterID(aName);
  if(id>-1){
    chatters[id].muted = !chatters[id].muted;
    if(chatters[id].muted)
      chat(chatters[id].name+" muted.");
    else
      chat(chatters[id].name+" unmuted.");
  }
  else{
    chat("Chatter with name "+aName+" not found.");
  }
}

function floodRefreshFive(){
  floodCounterFive = 0;
}

function floodRefreshTen(){
  floodCounterTen = 0;
}

function floodRefreshMinute(){
  floodCounterMinute = 0;
}

// Encapsulates an array of strings in one table row string.
function r(aElements){
  var row="<tr>";
  for(var i=0;i<aElements.length;i++){
    row+="<td>"+aElements[i]+"</td>";
  }
  row+="</tr>";
  return row;
}

/****************/
/* Account Page */
/****************/

// Loading status.
var STATUS_UNLOADED=0;
var STATUS_LOADING=1;
var STATUS_LOADED=2;

// Nationalities. (Update with nationalities.php)
var nationalities = new Array();
nationalities.push({'id':8,name:'Australia'});
nationalities.push({'id':19,name:'Austria'});
nationalities.push({'id':41,name:'Azeroth'});
nationalities.push({'id':15,name:'Belgium'});
nationalities.push({'id':28,name:'Brazil'});
nationalities.push({'id':22,name:'Bulgaria'});
nationalities.push({'id':23,name:'Canada'});
nationalities.push({'id':7,name:'China'});
nationalities.push({'id':21,name:'Croatia'});
nationalities.push({'id':20,name:'Denmark'});
nationalities.push({'id':30,name:'Egypt'});
nationalities.push({'id':38,name:'Equestria'});
nationalities.push({'id':13,name:'Finland'});
nationalities.push({'id':2,name:'France'});
nationalities.push({'id':3,name:'Germany'});
nationalities.push({'id':24,name:'Hungary'});
nationalities.push({'id':14,name:'Iceland'});
nationalities.push({'id':6,name:'India'});
nationalities.push({'id':32,name:'Indonesia'});
nationalities.push({'id':25,name:'Ireland'});
nationalities.push({'id':39,name:'Israel'});
nationalities.push({'id':17,name:'Italy'});
nationalities.push({'id':9,name:'Japan'});
nationalities.push({'id':33,name:'Korea'});
nationalities.push({'id':40,name:'Krypton'});
nationalities.push({'id':29,name:'Mexico'});
nationalities.push({'id':42,name:'Middle Earth'});
nationalities.push({'id':36,name:'Mongolia'});
nationalities.push({'id':35,name:'Morocco'});
nationalities.push({'id':12,name:'Norway'});
nationalities.push({'id':26,name:'Poland'});
nationalities.push({'id':31,name:'Portugal'});
nationalities.push({'id':10,name:'Russia'});
nationalities.push({'id':37,name:'Serbia'});
nationalities.push({'id':27,name:'Slovakia'});
nationalities.push({'id':16,name:'Spain'});
nationalities.push({'id':11,name:'Sweden'});
nationalities.push({'id':18,name:'Switzerland'});
nationalities.push({'id':1,name:'The Netherlands'});
nationalities.push({'id':4,name:'The United Kingdom'});
nationalities.push({'id':5,name:'The United States'});
nationalities.push({'id':34,name:'Turkey'});

// Text colors for donators. If new colors are added, server code has to be changed. Please alphabetize by name.
var textColors = new Array(
{name:"Black",color:"#000000"},
{name:"Blue",color:"#0000FF"},
{name:"Brown",color:"#A52A2A"},
{name:"Dark Cyan",color:"#307D7E"},
{name:"Dark Olive Green",color:"#667C26"},
{name:"Dark Rosy Brown",color:"#7F5A58"},
{name:"Green",color:"#008000"},
{name:"Hot Pink",color:"#F660AB"},
{name:"Purple",color:"#800080"},
{name:"Sienna",color:"#8A4117"}
);

// Text fonts for donators. If new fonts are added, server code has to be changed. Please alphabetize by font.
var textFonts = new Array(
{font:"Arial"},
{font:"Courier"},
{font:"Cursive"},
{font:"Fantasy"},
{font:"Garamond"},
{font:"Impact"},
{font:"Kristen ITC"},
{font:"Modern"},
{font:"Monospace"},
{font:"Roman"},
{font:"Script"},
{font:"Times"}
);

// The account object.
var account = new Object();
account.id=-1;

/* Account Details */
account.accountDetailsStatus=STATUS_UNLOADED;
account.email="";
account.gender=0;
account.sexuality=0;
account.nationality=0;
account.description=""; // Donators get more customisation options here later.
account.avatar="default_user.png";

/* Game Options */
account.gameOptionsStatus=STATUS_UNLOADED;
account.bgColor="";
account.boColor="";
account.titlesOn=false;
account.tipsOn=false;
account.soundOn=false;
account.musicOn=false;
account.soundVolume=0;
account.musicVolume=0;
account.winQuote="";
account.winVideo="";

/* Lobby Options */
account.lobbyOptionsStatus=STATUS_UNLOADED;
account.lobbySoundOn=false;
   
/* Donator Rewards */
account.donatorRewardsStatus=STATUS_UNLOADED;
account.donated=0;
account.joinQuote="";
account.suffixTitle="";
account.textColor=-1;
account.textFont=-1;
//account.textStyle=-1;

var unsavedChanges=false;

// Build the Account Page.
function accountPage(){
  var wrapper=$("#accountWrapper");
	wrapper.html("If you want to check out your profile page, go <a href='user.php?user="+myId+"'>here</a>.<br /><br />");
	
  // Add Account Details.
  wrapper.append("<div id='accountDetails'></div>");
  var accountDetails=$("#accountDetails");
  accountDetails.addClass("accountWrap");
  accountDetails.append("<div id='accountDetailsHeader'><div>Account Details</div></div>");
  accountDetails.append("<div id='accountDetailsContent'><div id='accountDetailsPanel'></div></div>");
  var accountDetailsHeader=$("#accountDetailsHeader");
  var accountDetailsContent=$("#accountDetailsContent");
  accountDetailsHeader.addClass("accountHeader unselectable");
  accountDetailsContent.addClass("accountContent");
  accountDetailsHeader.click(loadAccountDetails);
  
  // Add Game Options
  wrapper.append("<div id='gameOptions'></div>");
  var gameOptions=$("#gameOptions");
  gameOptions.addClass("accountWrap");
  gameOptions.append("<div id='gameOptionsHeader'><div>Game Options</div></div>");
  gameOptions.append("<div id='gameOptionsContent'><div id='gameOptionsPanel'></div></div>");
  var gameOptionsHeader=$("#gameOptionsHeader");
  var gameOptionsContent=$("#gameOptionsContent");
  gameOptionsHeader.addClass("accountHeader unselectable");
  gameOptionsContent.addClass("accountContent");
  gameOptionsHeader.click(loadGameOptions);
	
  // Add Lobby Options
  wrapper.append("<div id='lobbyOptions'></div>");
  var lobbyOptions=$("#lobbyOptions");
  lobbyOptions.addClass("accountWrap");
  lobbyOptions.append("<div id='lobbyOptionsHeader'><div>Lobby Options</div></div>");
  lobbyOptions.append("<div id='lobbyOptionsContent'><div id='lobbyOptionsPanel'></div></div>");
  var lobbyOptionsHeader=$("#lobbyOptionsHeader");
  var lobbyOptionsContent=$("#lobbyOptionsContent");
  lobbyOptionsHeader.addClass("accountHeader unselectable");
  lobbyOptionsContent.addClass("accountContent");
  lobbyOptionsHeader.click(loadLobbyOptions);
	
  // Add Donator Rewards
  wrapper.append("<div id='donatorRewards'></div>");
  var donatorRewards=$("#donatorRewards");
  donatorRewards.addClass("accountWrap");
  donatorRewards.append("<div id='donatorRewardsHeader'><div>Donator Rewards</div></div>");
  donatorRewards.append("<div id='donatorRewardsContent'><div id='donatorRewardsPanel'></div></div>");
  var donatorRewardsHeader=$("#donatorRewardsHeader");
  var donatorRewardsContent=$("#donatorRewardsContent");
  donatorRewardsHeader.addClass("accountHeader unselectable");
  donatorRewardsContent.addClass("accountContent");
  donatorRewardsHeader.click(loadDonatorRewards);
	
  $(".accountHeader").click(function(){
    var content = $(this).next();
    if(content.css("display")=="none")
      content.css("display","block");
    else
      content.css("display","none");
  });
	
	$("body").append("<div id='accountServerMessages'></div>");
	$("#accountServerMessages").mouseover(function(){
		$("#accountServerMessages").stop(true).animate({opacity:100},100);
	});
	$("#accountServerMessages").mouseout(function(){
		$("#accountServerMessages").animate({opacity:0},2000,function(){
			$("#accountServerMessages").css("display","none");
		});
	});
	
	window.onbeforeunload = function(){
		if(unsavedChanges)
			return "You have unsaved changes on your Account Page. If you leave now, those changes won't be saved.";
	};
	
	setInterval(accountPage_CheckForChanges,1000);
}

// Build the Account Details panel.
function buildAccountDetails(){
  var panel=$("#accountDetailsPanel").html("");
  
	panel.append(saveAllButton("AccountDetails"));
	
  // Gender.
  var genderHTML = "<div style='padding-top: 0;'><b>Gender</b><br />";
	var genderMale = (account.gender==0) ? " checked" : "";
	var genderFemale = (account.gender==1) ? " checked" : "";
	var genderUnknown = (account.gender==2) ? " checked" : "";
	genderHTML += "<input type='radio' name='gender' value='0'"+genderMale+" /> <b>I'm a manly man.</b><br />";
  genderHTML += "<input type='radio' name='gender' value='1'"+genderFemale+" /> <b>I'm a girly girl.</b><br />";
	genderHTML += "<input type='radio' name='gender' value='2'"+genderUnknown+" /> <b>I'm not quite sure what I am.</b>";
	genderHTML += "</div>";
	
	panel.append(genderHTML);
	
  // Sexuality.
  var sexualityHTML = "<div style='padding-top: 0;'><b>Sexuality</b><br />";
	var sexualityMale = (account.sexuality==0) ? " checked" : "";
	var sexualityFemale = (account.sexuality==1) ? " checked" : "";
	var sexualityUnknown = (account.sexuality==2) ? " checked" : "";
	sexualityHTML += "<input type='radio' name='sexuality' value='0'"+sexualityMale+" /> <b>I'm into guys!</b><br />";
  sexualityHTML += "<input type='radio' name='sexuality' value='1'"+sexualityFemale+" /> <b>I'm into girls.</b><br />";
	sexualityHTML += "<input type='radio' name='sexuality' value='2'"+sexualityUnknown+" /> <b>I love em all! Wooh!</b>";
  sexualityHTML += "</div>";
	
	panel.append(sexualityHTML);
	
  // Nationality.
  var nationalityHTML = "<div style='padding-top: 0;'><b>Nationality</b><br />";
	nationalityHTML += "<select name='nationality' id='nationality'>";
	for(var i=0; i<nationalities.length; i++){
		var checked="";
		if(nationalities[i].id==account.nationality)
			checked=" selected='selected'";
		nationalityHTML += "<option value='"+nationalities[i].id+"'"+checked+">"+nationalities[i].name+"</option>";	
	}
	nationalityHTML += "</select>";
  nationalityHTML += "</div>";
	
	panel.append(nationalityHTML);
	
  // Description.
  var descriptionHTML = "<div style='padding-top: 0;'><b>Personal Description</b><br />";
	descriptionHTML += "<textarea id='description' style='width: 400px; height: 100px;'>"+account.description+"</textarea><br />";
  descriptionHTML += "</div>";
	
	panel.append(descriptionHTML);
  
  // Avatar.
  var avatarHTML = "<div style='float: left; padding-top: 0;'><b>Avatar</b><br />";
	avatarHTML += "<image src='images/user/"+account.avatar+"' />";
  avatarHTML += "</div>";
	
	avatarHTML += "<div style='float: left;'>Image has to be a <b>PNG</b>, <b>JPG</b> or <b>JPEG</b>.<br />";
	avatarHTML += "Max size: <b>100x100</b> pixels.<br />";
	avatarHTML += "Max size: <b>50 KB</b>.<br />";
	avatarHTML += "If you want to change your avatar, please go to <a href='http://www.boardgame-online.com/avatar.php'>this page</a>.</div>";
	
	avatarHTML += "<div style='clear: both;'></div>";
  
	panel.append(avatarHTML);
	
  // Email.
  var emailHTML = "<div style='padding-top: 0;'><b>Email</b><br />";
	emailHTML += "<input type='text' id='email' style='width: 400px;' value='"+account.email+"' />";
  emailHTML += "</div>";
	
	panel.append(emailHTML);
	
  // Password.
  var passwordHTML = "<div style='padding-top: 0;'><b>Password</b><br />";
	passwordHTML += "<table>";
	passwordHTML += "<tr><td>Your current password </td><td><input id='changePassword_OldPassword' type='password' /></td></tr>";
	passwordHTML += "<tr><td>Your new password </td><td><input id='changePassword_NewPassword' type='password' /></td></tr>";
	passwordHTML += "<tr><td>Verify your new password &nbsp;&nbsp;&nbsp;</td><td><input id='changePassword_NewPasswordVerification' type='password' /></td></tr>";
	passwordHTML += "</table>";
	passwordHTML += "<button id='savePassword' onclick='saveNewPassword();'>Change Password</button>";
  passwordHTML += "</div>";
  
	panel.append(passwordHTML);
}

// Build the Game Options panel.
function buildGameOptions(){
  var panel=$("#gameOptionsPanel").html("");
  
	panel.append(saveAllButton("GameOptions"));
	
  // Background color and border color.
  var styleHTML = "<div style='padding-top: 0;'><b>Game Style</b><br />";
	
	styleHTML += styleButton("#FFFFFF","#000000","Black and White");;
	styleHTML += styleButton("#B9FFFF","#0000CC","Aqua");
	styleHTML += styleButton("#DCFFB4","#006E00","Spring");
	styleHTML += styleButton("#FFFF7D","#000000","Bee Hive");
	styleHTML += styleButton("#FFEEFF","#FF0099","Happy Pink");
	styleHTML += styleButton("#AF41FF","#00FFAE","Alien Atmosphere");
	styleHTML += styleButton("#FFD773","#820000","Autumn");
	
	styleHTML += "<div style='clear: both;'></div>";
	styleHTML += "<table style='float: left;'>";
	styleHTML += "<tr><td><b>Background Color</b>&nbsp;&nbsp;</td><td><input type='text' id='bgColor' disabled='disabled' value='"+account.bgColor+"' style='width: 70px;' /></td></tr>";
	styleHTML += "<tr><td><b>Border Color</b></td><td><input type='text' id='boColor' disabled='disabled' value='"+account.boColor+"' style='width: 70px;' /></td></tr>";
	styleHTML += "</table>";
	styleHTML += "<div id='selectedStyle' class='styleButton' style='background-color: "+account.bgColor+"; border-color: "+account.boColor+"; cursor: default; margin-left: 15px;'></div>";
	styleHTML += "<div style='clear: both;'></div>";
  styleHTML += "</div>";
	
	panel.append(styleHTML);
  
  // Titles on/off.
  var titlesHTML = "<div style='padding-top: 0; margin-top: -20px;'><b>Player Titles On/Off</b><br />";
	var titlesOn = account.titlesOn==1 ? " checked" : "";
	var titlesOff = account.titlesOn==0 ? " checked" : "";
	titlesHTML += "<input type='radio' name='titlesOn' value='1'"+titlesOn+" /> <b>ON</b><br />";
  titlesHTML += "<input type='radio' name='titlesOn' value='0'"+titlesOff+" /> <b>OFF</b><br />";
  titlesHTML += "</div>";
  
	panel.append(titlesHTML);
  
  // Tips on/off.
  var tipsHTML = "<div style='padding-top: 0;'><b>Tips On/Off</b><br />";
	var tipsOn = account.tipsOn==1 ? " checked" : "";
	var tipsOff = account.tipsOn==0 ? " checked" : "";
	tipsHTML += "<input type='radio' name='tipsOn' value='1'"+tipsOn+" /> <b>ON</b><br />";
  tipsHTML += "<input type='radio' name='tipsOn' value='0'"+tipsOff+" /> <b>OFF</b><br />";
  tipsHTML += "</div>";
  
	panel.append(tipsHTML);
  
  // Sound on/off.
  var soundHTML = "<div style='padding-top: 0;'><b>Sound On/Off</b><br />";
	var soundOn = account.soundOn==1 ? " checked" : "";
	var soundOff = account.soundOn==0 ? " checked" : "";
	soundHTML += "<input type='radio' name='soundOn' value='1'"+soundOn+" /> <b>ON</b><br />";
  soundHTML += "<input type='radio' name='soundOn' value='0'"+soundOff+" /> <b>OFF</b><br />";
  soundHTML += "</div>";
  
	panel.append(soundHTML);
  
  // Music on/off.
  var musicHTML = "<div style='padding-top: 0;'><b>Music On/Off</b><br />";
	var musicOn = account.musicOn==1 ? " checked" : "";
	var musicOff = account.musicOn==0 ? " checked" : "";
	musicHTML += "<input type='radio' name='musicOn' value='1'"+musicOn+" /> <b>ON</b><br />";
  musicHTML += "<input type='radio' name='musicOn' value='0'"+musicOff+" /> <b>OFF</b><br />";
  musicHTML += "</div>";
  
	panel.append(musicHTML);
  
  // Sound Volume.
  var soundVolumeHTML = "<div style='padding-top: 0;'><b>Sound Volume</b><br />";
	soundVolumeHTML += "<input id='soundVolume' name='soundVolume' type='text' style='width: 30px;' maxlength='3' />%";
  soundVolumeHTML += "</div>";
  
	panel.append(soundVolumeHTML);
	$("#soundVolume").val(account.soundVolume).change(cleanVolume);
	
  // Music Volume.
  var musicVolumeHTML = "<div style='padding-top: 0;'><b>Music Volume</b><br />";
	musicVolumeHTML += "<input id='musicVolume' name='musicVolume' type='text' style='width: 30px;' maxlength='3' />%";
  musicVolumeHTML += "</div>";
  
	panel.append(musicVolumeHTML);
	$("#musicVolume").val(account.musicVolume).change(cleanVolume);
	
  // Win quote.
  var winQuoteHTML = "<div style='padding-top: 0;'><b>Win Quote</b><br />";
	winQuoteHTML += "<input id='winQuote' name='winQuote' type='text' style='width: 400px;' />";
  winQuoteHTML += "</div>";
  
	panel.append(winQuoteHTML);
	$("#winQuote").val(account.winQuote);
  
  // Win video.
  var winVideoHTML = "<div style='padding-top: 0;'><b>Win Video</b><br />";
	winVideoHTML += "<input id='winVideo' name='winVideo' type='text' style='width: 400px;' /><button onclick='testWinVideo();'>Test Video!</button><br />";
	winVideoHTML += "<div id='testWinVideo'></div>";
  winVideoHTML += "</div>";
  
	panel.append(winVideoHTML);
	$("#winVideo").val(account.winVideo).change(cleanWinVideo);
}

// Build the Lobby Options panel.
function buildLobbyOptions(){
  var panel=$("#lobbyOptionsPanel").html("");
	
	panel.append(saveAllButton("LobbyOptions"));
	
  // Sound on/off.
  var soundHTML = "<div style='padding-top: 0;'><b>Sound On/Off</b><br />";
	var lobbySoundOn = account.lobbySoundOn==1 ? " checked" : "";
	var lobbySoundOff = account.lobbySoundOn==0 ? " checked" : "";
	soundHTML += "<input type='radio' name='lobbySoundOn' value='1'"+lobbySoundOn+" /> <b>ON</b><br />";
  soundHTML += "<input type='radio' name='lobbySoundOn' value='0'"+lobbySoundOff+" /> <b>OFF</b><br />";
  soundHTML += "</div>";
  
	panel.append(soundHTML);
}

// Build the Donator Rewards panel.
function buildDonatorRewards(){
  var panel=$("#donatorRewardsPanel").html("");
	var isUnlocked=false;
	var UNLOCKED = "<b style='color: #008800; margin-left: 10px;'>(Unlocked!)</b>";
	var LOCKED = "<b style='color: #BB0000; margin-left: 10px;'>(Not yet unlocked!)</b>";
	
	panel.append(saveAllButton("DonatorRewards"));
	
  // Golden name: lobby.
	isUnlocked = account.donated>=100;
	panel.append("<div><b>&euro;1,00 - Golden Name: Lobby (Passive)</b>"+(isUnlocked ? UNLOCKED : LOCKED)+"<br />Your name will appear as gold in the lobby.</div>");
	
  // Donator item: Horn.
	isUnlocked = account.donated>=100;
	panel.append("<div><b>&euro;1,00 - Item: Horn (In-Game)</b>"+(isUnlocked ? UNLOCKED : LOCKED)+"<br />The Horn is a novelty item that can be used make a HONK HONK sound. Has three charges.</div>");
		
  // Join Quote 
	isUnlocked = account.donated>=300;
	var joinQuoteHTML = "<div><b>&euro; 3,00 - Join Quote (In-Game)</b>"+(isUnlocked ? UNLOCKED : LOCKED)+"<br />";
	joinQuoteHTML += "You can set your personal join quote, which appears right after you join a game.<br />";
	joinQuoteHTML += "Join Quote: <input id='joinQuote' type='text' maxlength='80' style='width: 120px;' /> (Max 80 characters)";
	panel.append(joinQuoteHTML);
	if(!isUnlocked){
		$("#joinQuote").attr("disabled","disabled");
	}
	else{
		$("#joinQuote").val(account.joinQuote);
	}
	
  // Golden name: lobby.
	isUnlocked = account.donated>=500;
	panel.append("<div><b>&euro;5,00 - Golden Name: In-Game (Passive)</b>"+(isUnlocked ? UNLOCKED : LOCKED)+"<br />Your name will appear as gold in the game.</div>");

	// Suffix Title
	isUnlocked = account.donated>=700;
	var suffixTitleHTML = "<div><b>&euro; 7,00 - Suffix Title (In-Game)</b>"+(isUnlocked ? UNLOCKED : LOCKED)+"<br />";
	suffixTitleHTML += "You can set your own personal suffix title, which appears right after your name in the game. Have you always wanted to be <b>Billy The Kid</b> or <b>Bert The Awesome</b>? Here's your chance!<br />";
	suffixTitleHTML += "Title: <input id='suffixTitle' type='text' maxlength='17' style='width: 120px;' /> (Max 17 characters)";
	panel.append(suffixTitleHTML);
	if(!isUnlocked){
		$("#suffixTitle").attr("disabled","disabled");
	}
	else{
		$("#suffixTitle").val(account.suffixTitle);
	}
	
  // Chat text options.
	isUnlocked = account.donated>=1000;
	
  var textHTML = "<div style='padding-top: 0;'><b>&euro;10,00 - Chat Text Options (In-Game)</b>"+(isUnlocked ? UNLOCKED : LOCKED)+"<br />";
	textHTML += "<br />";
	textHTML += "<div style='padding: 0; margin-top: -4px;;'></div>";
	textHTML += "Text Color: <select name='textColor' id='textColor'>";
	for(var i=0; i<textColors.length; i++){
		var checked="";
		if(textColors[i].color==account.textColor)
			checked=" selected='selected'";
		textHTML += "<option value='"+textColors[i].color+"'"+checked+" style='color: "+textColors[i].color+";'>"+textColors[i].name+"</option>";	
	}
	textHTML += "</select> ";
	
	textHTML += "Text Font: <select name='textFont' id='textFont'>";
	for(var i=0; i<textFonts.length; i++){
		var checked="";
		if(textFonts[i].font==account.textFont)
			checked=" selected='selected'";
		textHTML += "<option value='"+textFonts[i].font+"'"+checked+" style='font-family: "+textFonts[i].font+";'>"+textFonts[i].font+"</option>";	
	}
	textHTML += "</select>";
	
	// TODO: Add cursive option?
	
  textHTML += "</div>";
	
	panel.append(textHTML);
	
	if(!isUnlocked){
		$("#textColor").attr("disabled","disabled");
		$("#textFont").attr("disabled","disabled");
	}
	
	
}

// Load the Account Details information.
function loadAccountDetails(){
  if(account.accountDetailsStatus==STATUS_UNLOADED){ // Do AJAX request.
    account.accountDetailsStatus=STATUS_LOADING;
    $.ajax({
      url: "account/requestAccountDetails.php",
			type: "post",
      dataType : "xml",
      cache: false,
      success: accountCallback
    });
    $("#accountDetailsPanel").html("Loading...");
  }
  else if(account.accountDetailsStatus==STATUS_LOADING){
    $("#accountDetailsPanel").html("Still loading...");
  }
} 

// Load the Game Options information.
function loadGameOptions(){
  if(account.gameOptionsStatus==STATUS_UNLOADED){ // Do AJAX request.
    account.gameOptionsStatus=STATUS_LOADING;
    $.ajax({
      url: "account/requestGameOptions.php",
      type: "post",
      dataType : "xml",
      cache: false,
      success: accountCallback
    });
    $("#gameOptionsPanel").html("Loading...");
  }
  else if(account.gameOptionsStatus==STATUS_LOADING){ // Still loading...
    $("#gameOptionsPanel").html("Still loading...");
  }
}

// Load the Lobby Options information.
function loadLobbyOptions(){
  if(account.lobbyOptionsStatus==STATUS_UNLOADED){ // Do AJAX request.
    account.lobbyOptionsStatus=STATUS_LOADING;
    $.ajax({
      url: "account/requestLobbyOptions.php",
      type: "post",
      dataType : "xml",
      cache: false,
      success: accountCallback
    });
    $("#lobbyOptionsPanel").html("Loading...");
  }
  else if(account.lobbyOptionsStatus==STATUS_LOADING){ // Still loading...
    $("#lobbyOptionsPanel").html("Still loading...");
  }
}

// Load the Donator Rewards information.
function loadDonatorRewards(){
  if(account.donatorRewardsStatus==STATUS_UNLOADED){ // Do AJAX request.
    account.donatorRewardsStatus=STATUS_LOADING;
    $.ajax({
      url: "account/requestDonatorRewards.php",
      type: "post",
      dataType : "xml",
      cache: false,
      success: accountCallback
    });
    $("#donatorRewardsPanel").html("Loading...");
  }
  else if(account.donatorRewardsStatus==STATUS_LOADING){ // Still loading...
    $("#donatorRewardsPanel").html("Still loading...");
  }
}

// Handles server response.
function accountCallback(responseXML,aStatus){
  if(aStatus=="success"){
    // Get the root.
    xmlDoc=responseXML.getElementsByTagName("x")[0];
		
    if(xmlDoc==null)
      return;
    
    for(var inode_counter=0;inode_counter<xmlDoc.childNodes.length;inode_counter++){
      var x=xmlDoc.childNodes[inode_counter];
  	  try{
        switch(x.nodeName){
          case "_AccountDetails": // Account details have loaded.
						account.accountDetailsStatus=STATUS_LOADED;
            buildAccountDetails();
            break;
        
          case "_GameOptions": // Game options have loaded.
            account.gameOptionsStatus=STATUS_LOADED;
						buildGameOptions();
            break;
            
          case "_LobbyOptions": // Lobby options have loaded.
            account.lobbyOptionsStatus=STATUS_LOADED;
						buildLobbyOptions();
            break;
					
          case "_DonatorRewards": // Donator Rewards have loaded.
            account.donatorRewardsStatus=STATUS_LOADED;
						buildDonatorRewards();
            break;
						
          case "_Success": // A success message!
            var message=x.childNodes[0].nodeValue;
						accountServerMessage(message,ACCOUNT_SERVER_MESSAGE_SUCCESS);
            break;
						
          case "_Failure": // A failure message!
            var message=x.childNodes[0].nodeValue;
						accountServerMessage(message,ACCOUNT_SERVER_MESSAGE_FAILURE);
            break;
					
          case "avatar":
            account.avatar=x.childNodes[0].nodeValue;
            break;
						
          case "bgColor":
            account.bgColor=x.childNodes[0].nodeValue;
						$("#selectedStyle").css("background-color",account.bgColor);
            break;
						
          case "boColor":
            account.boColor=x.childNodes[0].nodeValue;
						$("#selectedStyle").css("border-color",account.boColor);
            break;
					
          case "description":
						if(x.childNodes[0]!=null && x.childNodes[0].nodeValue!=""){
							account.description=x.childNodes[0].nodeValue;
						}
						if(account.accountDetailsStatus==STATUS_LOADED)
							$("#description").val(account.description);
            break;
					
          case "donated":
            account.donated=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "email":
            account.email=x.childNodes[0].nodeValue;
            break;
					
          case "gender":
            account.gender=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "joinQuote":
            if(x.childNodes[0]!=null && x.childNodes[0].nodeValue!=""){
							account.joinQuote=x.childNodes[0].nodeValue;
							if($("#joinQuote").length==1)
								$("#joinQuote").val(account.joinQuote);
						}
            break;
					
          case "lobbySoundOn":
            account.lobbySoundOn=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "musicOn":
            account.musicOn=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "musicVolume":
            account.musicVolume=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "nationality":
						account.nationality=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "password":
						$("#changePassword_OldPassword").val("");
						$("#changePassword_NewPassword").val("");
						$("#changePassword_NewPasswordVerification").val("");
            break;
					
          case "sexuality":
            account.sexuality=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "soundOn":
            account.soundOn=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "soundVolume":
            account.soundVolume=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "suffixTitle":
						if(x.childNodes[0]!=null && x.childNodes[0].nodeValue!=""){
							account.suffixTitle=x.childNodes[0].nodeValue;
							if($("#suffixTitle").length==1)
								$("#suffixTitle").val(account.suffixTitle);
						}
            break;
					
          case "textColor":
            account.textColor=x.childNodes[0].nodeValue;
            break;
					
          case "textFont":
            account.textFont=x.childNodes[0].nodeValue;
            break;
					
          case "tipsOn":
            account.tipsOn=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "titlesOn":
            account.titlesOn=parseInt(x.childNodes[0].nodeValue);
            break;
					
          case "winQuote":
            account.winQuote=x.childNodes[0].nodeValue;
            break;
						
          case "winVideo":
            account.winVideo=x.childNodes[0].nodeValue;
            break;
        
          case "example": // Example.
            var content=x.childNodes[0].nodeValue;
            var attribute=parseInt(x.getAttribute("attribute"));
            break;
					
          default:
            //alert("Unknown XML tag from server: "+x.nodeName);
        }
	    }
      catch(err){
		    //alert("JavaScript Error on line "+err.lineNumber+": "+err.toString());
		  }
    }
  }
}

function saveAllButton(type){
	var button =
	"<div class='saveAllDiv saveAllSaved saveAll"+type+"Div'>"+
		"<span class='saveAllInnerSpan'>"+
			"<img class='saveAllIcon saveAll"+type+"Icon' src='images/saved.png' /> "+
			"<button onclick='saveOption(\""+type+"\");' class='saveAllButton "+type+" saveAll"+type+"Button' disabled='disabled'>Save</button> "+
			"<span class='saveAllText saveAll"+type+"Text'>Loading...</span>"+
		"</span>"+
	"</div>";
	return button;
}

// This function is called whenever a Save button is clicked.
// Based on the button ID, it will know what to save.
function saveOption(type){
	switch(type){
		case "AccountDetails":
			if(account.email!=$("#email").val()){
				var val = $("#email").val();
				saveQuery("update_email",{email : val});
			}
			if(account.gender!=$("input[name=gender]:checked").val()){
				var val = $("input[name=gender]:checked").val();
				saveQuery("update_gender",{gender : val});
			}
			if(account.sexuality!=$("input[name=sexuality]:checked").val()){
				var val = $("input[name=sexuality]:checked").val();
				saveQuery("update_sexuality",{sexuality : val});
			}
			if(account.nationality!=$("#nationality").val()){
				var val = $("#nationality").val();
				saveQuery("update_nationality",{nationality : val});
			}
			if(account.description!=$("#description").val()){
				var val = $("#description").val();
				saveQuery("update_description",{description : val});
			}
			break;
		
		case "GameOptions":
			if(account.bgColor!=$("#bgColor").val() || account.boColor!=$("#boColor").val()){
				var val1 = $("#bgColor").val();
				var val2 = $("#boColor").val();
				saveQuery("update_style",{bgColor : val1, boColor : val2});
			}
			if(account.titlesOn!=$("input[name=titlesOn]:checked").val()){
				var val = $("input[name=titlesOn]:checked").val();
				saveQuery("update_titlesOn",{titlesOn : val});
			}
			if(account.tipsOn!=$("input[name=tipsOn]:checked").val()){
				var val = $("input[name=tipsOn]:checked").val();
				saveQuery("update_tipsOn",{tipsOn : val});
			}
			if(account.soundOn!=$("input[name=soundOn]:checked").val()){
				var val = $("input[name=soundOn]:checked").val();
				saveQuery("update_soundOn",{soundOn : val});
			}
			if(account.musicOn!=$("input[name=musicOn]:checked").val()){
				var val = $("input[name=musicOn]:checked").val();
				saveQuery("update_musicOn",{musicOn : val});
			}
			if(account.soundVolume!=$("#soundVolume").val()){
				var val = $("#soundVolume").val();
				saveQuery("update_soundVolume",{soundVolume : val});
			}
			if(account.musicVolume!=$("#musicVolume").val()){
				var val = $("#musicVolume").val();
				saveQuery("update_musicVolume",{musicVolume : val});
			}
			if(account.winQuote!=$("#winQuote").val()){
				var val = $("#winQuote").val();
				saveQuery("update_winQuote",{winQuote : val});
			}
			if(account.winVideo!=$("#winVideo").val()){
				var val = $("#winVideo").val();
				saveQuery("update_winVideo",{winVideo : val});
			}
			break;
		
		case "LobbyOptions":
			if(account.lobbySoundOn!=$("input[name=lobbySoundOn]:checked").val()){
				var val = $("input[name=lobbySoundOn]:checked").val();
				saveQuery("update_lobbySoundOn",{lobbySoundOn : val});
			}
			break;
		
		case "DonatorRewards":
			if(account.joinQuote!=$("#joinQuote").val()){
				var val = $("#joinQuote").val();
				saveQuery("update_joinQuote",{joinQuote : val});
			}
			if(account.suffixTitle!=$("#suffixTitle").val()){
				var val = $("#suffixTitle").val();
				saveQuery("update_suffixTitle",{suffixTitle : val});
			}
			if(account.textColor!=$("#textColor").val() || account.textFont!=$("#textFont").val()){
				var val = $("#textColor").val();
				var val2 = $("#textFont").val();
				saveQuery("update_chatStyle",{textColor : val, textFont : val2});
			}
			break;
		
		default:
		alert("ERROR: Save command not recognized: "+type);
	}
}

function saveNewPassword(){
  var pw = $("#changePassword_OldPassword").val();
	var pw_new1 = $("#changePassword_NewPassword").val();
	var pw_new2 = $("#changePassword_NewPasswordVerification").val();
	
	if(pw_new1!=pw_new2){
		alert("Your new passwords didn't match. Please re-enter them!");
		$("#changePassword_NewPassword").val("");
		$("#changePassword_NewPasswordVerification").val("");
		return;
	}
	
	var oldPasswordHashed=RMDstring(mySalt+pw);
	oldPasswordHashed=RMDstring(myNonce+oldPasswordHashed);
	var newPasswordHashed=RMDstring(mySalt+pw_new1);
	
	saveQuery("update_password",{oldPassword : oldPasswordHashed, newPassword : newPasswordHashed});
}

function saveQuery(script,toSend){
  $.ajax({
    url: "account/"+script+".php",
    type: "post",
    dataType : "xml",
    data: toSend,
    cache: false,
    success: accountCallback
  });
}

// On the account page, this function is performed every .5 seconds to check if any data has changed.
// If any category's data has been altered, the corresponding save panels will change.
function accountPage_CheckForChanges(){
	_unsavedChanges=false;
	if(account.accountDetailsStatus==STATUS_LOADED){ // Check account details.
		var upToDate=true;
		if(account.email!=$("#email").val() ||
			 account.gender!=$("input[name=gender]:checked").val() ||
			 account.sexuality!=$("input[name=sexuality]:checked").val() ||
			 account.nationality!=$("#nationality").val() ||
			 account.description!=$("#description").val())
			upToDate=false;
		
		if(upToDate){
			$(".saveAllAccountDetailsDiv").removeClass("saveAllUnsaved").addClass("saveAllSaved");
			$(".saveAllAccountDetailsIcon").attr("src","images/saved.png");
			$(".saveAllAccountDetailsButton").attr("disabled","disabled");
			$(".saveAllAccountDetailsText").html("Your account details are up to date!");
		}
		else{
			$(".saveAllAccountDetailsDiv").removeClass("saveAllSaved").addClass("saveAllUnsaved");
			$(".saveAllAccountDetailsIcon").attr("src","images/unsaved.png");
			$(".saveAllAccountDetailsButton").removeAttr("disabled");
			$(".saveAllAccountDetailsText").html("Your account details contain unsaved changes!");
			_unsavedChanges=true;
		}
	}
	
	if(account.gameOptionsStatus==STATUS_LOADED){ // Check game options.
		var upToDate=true;
		if(account.bgColor!=$("#bgColor").val() ||
			 account.boColor!=$("#boColor").val() ||
			 account.titlesOn!=$("input[name=titlesOn]:checked").val() ||
			 account.tipsOn!=$("input[name=tipsOn]:checked").val() ||
			 account.soundOn!=$("input[name=soundOn]:checked").val() ||
			 account.musicOn!=$("input[name=musicOn]:checked").val() ||
			 account.soundVolume!=$("#soundVolume").val() ||
			 account.musicVolume!=$("#musicVolume").val() ||
			 account.winQuote!=$("#winQuote").val() ||
			 account.winVideo!=$("#winVideo").val())
			upToDate=false;
		
		if(upToDate){
			$(".saveAllGameOptionsDiv").removeClass("saveAllUnsaved").addClass("saveAllSaved");
			$(".saveAllGameOptionsIcon").attr("src","images/saved.png");
			$(".saveAllGameOptionsButton").attr("disabled","disabled");
			$(".saveAllGameOptionsText").html("Your game options are up to date!");
		}
		else{
			$(".saveAllGameOptionsDiv").removeClass("saveAllSaved").addClass("saveAllUnsaved");
			$(".saveAllGameOptionsIcon").attr("src","images/unsaved.png");
			$(".saveAllGameOptionsButton").removeAttr("disabled");
			$(".saveAllGameOptionsText").html("Your game options contain unsaved changes!");
			_unsavedChanges=true;
		}
	}
	
	if(account.lobbyOptionsStatus==STATUS_LOADED){ // Check lobby options.
		var upToDate=true;
		if(account.lobbySoundOn!=$("input[name=lobbySoundOn]:checked").val())
			upToDate=false;
		
		if(upToDate){
			$(".saveAllLobbyOptionsDiv").removeClass("saveAllUnsaved").addClass("saveAllSaved");
			$(".saveAllLobbyOptionsIcon").attr("src","images/saved.png");
			$(".saveAllLobbyOptionsButton").attr("disabled","disabled");
			$(".saveAllLobbyOptionsText").html("Your lobby options are up to date!");
		}
		else{
			$(".saveAllLobbyOptionsDiv").removeClass("saveAllSaved").addClass("saveAllUnsaved");
			$(".saveAllLobbyOptionsIcon").attr("src","images/unsaved.png");
			$(".saveAllLobbyOptionsButton").removeAttr("disabled");
			$(".saveAllLobbyOptionsText").html("Your lobby options contain unsaved changes!");
			_unsavedChanges=true;
		}
	}
	
	if(account.donatorRewardsStatus==STATUS_LOADED){ // Check donator rewards.
		var upToDate=true;
		if( (account.joinQuote!=$("#joinQuote").val() && !$("#joinQuote").attr("disabled")) ||
				(account.suffixTitle!=$("#suffixTitle").val() && !$("#suffixTitle").attr("disabled")) ||
			  (account.textColor!=$("#textColor").val() && !$("#textColor").attr("disabled")) ||
			  (account.textFont!=$("#textFont").val() && !$("#textFont").attr("disabled")))
			upToDate=false;
		
		if(upToDate){
			$(".saveAllDonatorRewardsDiv").removeClass("saveAllUnsaved").addClass("saveAllSaved");
			$(".saveAllDonatorRewardsIcon").attr("src","images/saved.png");
			$(".saveAllDonatorRewardsButton").attr("disabled","disabled");
			$(".saveAllDonatorRewardsText").html("Your donator rewards are up to date!");
		}
		else{
			$(".saveAllDonatorRewardsDiv").removeClass("saveAllSaved").addClass("saveAllUnsaved");
			$(".saveAllDonatorRewardsIcon").attr("src","images/unsaved.png");
			$(".saveAllDonatorRewardsButton").removeAttr("disabled");
			$(".saveAllDonatorRewardsText").html("Your donator rewards contain unsaved changes!");
			_unsavedChanges=true;
		}
	}
	unsavedChanges=_unsavedChanges;
}

function styleButton(bgColor,boColor,tooltip){
	return "<div class='styleButton' style='background-color: "+bgColor+"; border-color: "+boColor+";' onclick='selectGameStyle(this);' title='"+tooltip+"'></div>";
}

function selectGameStyle(button){
	var bgColor = rgbToHex(button.style.backgroundColor);
	var boColor = rgbToHex(button.style.borderColor);
	$("#bgColor").val(bgColor);
	$("#boColor").val(boColor);
	$("#selectedStyle").css("background-color",bgColor);
	$("#selectedStyle").css("border-color",boColor);
}

// Called when the user puts in a new win video.
function cleanVolume(){
	var soundVolume = parseInt($("#soundVolume").val());
	var musicVolume = parseInt($("#musicVolume").val());
	soundVolume = (soundVolume>=0) ? soundVolume : 0;
	soundVolume = (soundVolume<=100) ? soundVolume : 100;
	musicVolume = (musicVolume>=0) ? musicVolume : 0;
	musicVolume = (musicVolume<=100) ? musicVolume : 100;
	$("#soundVolume").val(soundVolume);
	$("#musicVolume").val(musicVolume);
}

// Called when the user puts in a new win video.
function cleanWinVideo(){
	$("#winVideo").val( extractYoutubeID($("#winVideo").val()) );
}

function testWinVideo(){
	var winVideo = $("#winVideo").val();
	winVideo = extractYoutubeID(winVideo);
	$("#testWinVideo").html("<iframe width='420' height='345' src='http://www.youtube.com/embed/"+winVideo+"?autoplay=1' frameborder='0' allowfullscreen></iframe>");
}

function extractYoutubeID(link){
	// Remove everything before the v=
	var vPos = link.indexOf('v=');
	if(vPos!=-1) {
		link = link.substring(vPos+2);
	}
	
	// Remove anything after the first ampersand, if there is an ampersand.
	var aPos = link.indexOf('&');
	if(aPos!=-1) {
		link = link.substring(0, aPos);
	}
	
	// Now the link should be 11 characters long.
	return link.length==11 ? link : "";
}

var ACCOUNT_SERVER_MESSAGE_SUCCESS = 0;
var ACCOUNT_SERVER_MESSAGE_FAILURE = 1;
function accountServerMessage(msg,type){
	$("#accountServerMessages").css("display","block").stop(true).animate({opacity:100},100);
	if(type==ACCOUNT_SERVER_MESSAGE_SUCCESS){
		$("#accountServerMessages").append("<span style='color: #008800'>"+msg+"</span><br />");
	}
	else{
		$("#accountServerMessages").append("<span style='color: #BB0000'>"+msg+"</span><br />");
	}
	$("#accountServerMessages").attr("scrollTop",$("#accountServerMessages").attr("scrollHeight")).animate({opacity:0},4000,function(){
		$("#accountServerMessages").css("display","none");
	});
}

/***********/
/* General */
/***********/

function rgbToHex(rgb){
	if(rgb[0]=="#")
		return rgb;
	var colors = rgb.split(",");
	var r = intToHex(colors[0]);
	var g = intToHex(colors[1]);
	var b = intToHex(colors[2]);
	return "#"+r+g+b;
}

function intToHex(num){
	var hex = parseInt(num.replace(/[^\d.]/g,"")).toString(16).toUpperCase();
	return hex.length==2 ? hex : "0"+hex;
}
