// 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;
var xmlHttp2=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 isAsian=false;
var isCrazy=false;
var isDrunk=false;
var isPirate=false;
var isStoned=false;

var soundOn=true;
var soundGame=null;
var soundChat=null;
var extraSounds=new Array();
var soundParsed=false;
var volume=75;

var numChatters=0;
var chatters=new Array();
var seed=Math.floor(( Math.random()*3000 ));

var targetName="";

var playlistHandle=null;
var autoPlay=false;
var SONG_INTERVAL=2000;
var currentSongID=-1;
var numMoviesInPlaylist=0;
var currentPlaylistSong=-1;
var shuffleOn=false;

// 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();
  if(el("chatPane"))
  {
    enterChat();

    if(window.body) // IE
      window.body.onunload=leaveChat;
    else // FF
      window.onunload=leaveChat;
    
    el("chatInput").focus=false;
    
    setInterval(updateChat,1500);
    setInterval(chatCheck,120000);
    setTimeout(updateGames,1000);
    setInterval(updateGames,100000);
    chatters[numChatters]=new Object();
    chatters[numChatters].id=id;
    numChatters++;
  }

  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);
    }
  }
}

// Sets the browser variable.
function setBrowser(){
  browser=navigator.appName;
}

// Handles keyboard input.
function onkeyhitDocument(e){
  var charCode = (e.keyCode) ? e.keyCode : e.which;
  if(charCode == 13)
  {
    if (el("Login"))
    {
      getsalt();
    }
  }
  else if(charCode==32 && el("chatPane"))
  {
    if(!el("chatInput").focus)
    {
      jukeRand();
      e.preventDefault();
    }
  }
  // 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="/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="/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;var salt;var nonce;

    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);
    }

    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(){
  if(xmlHttp==null)
    return;
  
  if(xmlHttp.readyState==4)
  {
    if(xmlHttp.status!=200)
    {
      xmlHttp.send(lastSend);
      return;
    }
    
    if(xmlHttp.responseXML==null)
    {
      xmlHttp=null;
      return;
    }
    
    // Get the root.
    var xmlDoc=xmlHttp.responseXML.getElementsByTagName("x")[0];
    
    if(xmlDoc==null)
    {
      xmlHttp=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":
            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);
            
            chat("("+hours+":"+minutes+") "+chatText);
            
            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 "gd":
            var gid=x.getAttribute("id");
            var pane=el("openPane");
            if( el("openGame"+gid) )
              pane.removeChild( el("openGame"+gid) );
            if(pane.getElementsByTagName("span").length==1)
              pane.innerHTML="";
            var pane=el("runningPane");
            if( el("runningGame"+gid) )
              pane.removeChild( el("runningGame"+gid) );
            if(pane.getElementsByTagName("span").length==1)
              pane.innerHTML="";
            break;
          case "gn":
            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":
            var gname=x.childNodes[0].nodeValue;
            var gid=x.getAttribute("id");
            var creator=x.getAttribute("c");
            var finish=x.getAttribute("f");
            var pane=el("openPane");
            if( pane.innerHTML=="" )
              pane.innerHTML+="<br /><span class='chat''><b>Open games:</b><br /></span>";
            if( !el("openGame"+gid) )
              pane.innerHTML+="<span class='chat' id='openGame"+gid+"'><a 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":
            var gname=x.childNodes[0].nodeValue;
            var gid=x.getAttribute("id");
            var num=x.getAttribute("n");
            var creator=x.getAttribute("c");
            var finish=x.getAttribute("f");
            var pane=el("runningPane");
            if( pane.innerHTML=="" )
              pane.innerHTML+="<br /><span class='chat''><b>Running games:</b><br /></span>";
            if( !el("runningGame"+gid) )
              pane.innerHTML+="<span class='chat' id='runningGame"+gid+"'><a 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":
            lastUpdate=parseInt(x.childNodes[0].nodeValue);
            break;
        	case "j":
            var movieID=x.childNodes[0].nodeValue;
            var length=parseInt(x.getAttribute("l"));
            currentSongID=parseInt(x.getAttribute("i"));
            loadMovie(movieID);
            if(playlistHandle!=null)
              clearTimeout(playlistHandle);
            playlistHandle=setTimeout(nextSong,length*1000+SONG_INTERVAL);
            break;
          case "m":
            chat(x.childNodes[0].nodeValue);
            break;
          case "u":
            id=parseInt(x.getAttribute("id"));
            if(id>0) // Chatter enters.
            {
              var name=x.childNodes[0].nodeValue;
              var priv=x.getAttribute("pr");
              addChatter(id,name,priv);
            }
            else // Chatter leaves.
            {
              id*=-1;
              removeChatter(id);
            }
            break;
          default:
            chat("Unknown XML tag from server: "+x.nodeName);
        }
	    }
      catch(err)
      {
		    chat("JavaScript Error on line "+err.lineNumber+": "+err.toString());
		  }
    }
    xmlHttp=null;
  }
}

// A player enters the chat.
function addChatter(id,name,privileges){
  var style="";
  if(privileges>0)
    style="admin";
  
  chatters[numChatters]=new Object();
  chatters[numChatters].id=id;
  chatters[numChatters].name=name;
  chatters[numChatters].priv=privileges;
  el("usersPane").innerHTML+="<span class='chat' id='chatter"+id+"'><a class='"+style+"' href='user.php?user="+id+"' target='_blank'>"+name+"</a><br /></span>";
  numChatters++;
}

// A player leaves the chat.
function removeChatter(id){
  for(var i in chatters)
  {
    if(chatters[i].id==id)
    {
      chatters.splice(i,1);
      numChatters--;
      var child=el("chatter"+id);
      var parent=el("usersPane");
      parent.removeChild(child);
      break;
    }
  }
}

// Send a chat message to the server.
function sendChat(){
  var str=el("chatInput").value;
  el("chatInput").value="";
  
  for(var i=0;i<str.length;i++)
  {
    if(str[0]==" ")
    {
      str=str.slice(1);
      i--;
    }
    else if(str[0]=="/")
    {
      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 )
      {
        url="chatJukefind";
        if( str.search("jukefind ")==1 )
          str=str.substr(9);
        else if( str.search("jf ")==1 )
          str=str.substr(3);
        else
          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;
      }
      
      if(url!="")
      {
        str=strEncode(str);
        request(url+=".php?p="+myId+"&i="+lastUpdate,"c="+str);
        return;
      }
      
      switch(str)
      {
        case "/crazy":
          if(isCrazy)
            isCrazy=false;
          else
            isCrazy=true;
          break;
        case "/pirate":
          if(isPirate)
            isPirate=false;
          else
            isPirate=true;
          break;
        case "/stoned":
          if(isStoned)
            isStoned=false;
          else
            isStoned=true;
          break;
        case "/drunk":
          if(isDrunk)
            isDrunk=false;
          else
            isDrunk=true;
          break;
        case "/asian":
          if(isAsian)
            isAsian=false;
          else
            isAsian=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>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>/jf</b> [search text] to search the jukebox for music.");
          chat("<b>/video</b> [youtube link] to share a youtube video with everyone in the chat.");
          return;
      }
      break;
    }
    else
    {
      break;
    }
  }
  
  if(str[0]!="/")
  {
    if(str=="")
      return;
    if(isCrazy)
      str=makeCrazy(str);
    if(isPirate)
      str=makePirate(str);
    if(isStoned)
      str=makeStoned(str);
    if(isDrunk)
      str=makeDrunk(str);
    if(isAsian)
      str=makeAsian(str);
  }
  
  str=strEncode(str);
  
  request("chat.php?p="+myId+"&i="+lastUpdate,"c="+str,true);
}

// Asks the server if there are chat updates.
function updateChat(){
  request("updateChat.php?i="+lastUpdate,null,false);
}

// Tells the server you have entered the chat.
function enterChat(){
  request("enterChat.php?i="+lastUpdate,null,true);
}

// Tells the server you are leaving the chat.
function leaveChat(){
  request("leaveChat.php?i="+lastUpdate,null,true);
}

// Tell the server you are still in the chat.
function chatCheck(){
  request("chatCheck.php?i="+lastUpdate,null,false);
}

// Ask the server for updated information about current games.
function updateGames(){
  request("updateGames.php?i="+lastUpdate,null,false);
  el("openPane").innerHTML="";
  el("runningPane").innerHTML="";
}

// Send a request to the server.
function request(script,toSend, priority){
  if(xmlHttp==null || priority || nullCounter>=4)
  {
    lastSend = toSend;
    xmlHttp=newxmlrequest();
    xmlHttp.onreadystatechange=updatecallback;
    xmlHttp.open("POST",script,true);
    xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    xmlHttp.send(toSend);
    nullCounter=0;
  }
  else
  {
    nullCounter++;
  }
}

// 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(/ are /g," be ");
  txt=txt.replace(/Are /g,"Be ");
  txt=txt.replace(/hello/g,"ahoy");
  txt=txt.replace(/Hello/g,"Ahoy");
  txt=txt.replace(/hi /g,"ahoy ");
  txt=txt.replace(/Hi /g,"Ahoy ");
  txt=txt.replace(/hey/g,"ahoy");
  txt=txt.replace(/Hey/g,"Ahoy");
  
  var rand=Math.random();
  if(rand<=0.1)
    txt+=" Arrrr, matey!";
  else if(rand<=0.2)
    txt="Shiver me timbers! "+text;
  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! "+text;
  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;
}

// 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;
  }
}

// Load a YouTube movie below the chat.
function loadMovie(link){
  el("jukediv").innerHTML="<object width='425' height='344'><param id='movieObject' name='movie' value='http://www.youtube.com/v/"+link+"&hl=en&fs=1&autoplay=1&border=1'></param><param name='allowFullScreen' value='true'></param><param name='allowscriptaccess' value='always'></param><embed id='movieEmbed' src='http://www.youtube.com/v/"+link+"&hl=en&fs=1&autoplay=1&border=1' type='application/x-shockwave-flash' allowscriptaccess='always' allowfullscreen='true' width='425' height='344'></embed></object>";
  if(el(link))
  {
    var length=parseInt(el(link).name);
    if(length<1)
      return;
    if(playlistHandle!=null)
      clearTimeout(playlistHandle);
    playlistHandle=setTimeout(nextSong,length*1000+SONG_INTERVAL);
  }
}

// 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>";
  
  /*
  if(playlistHandle==null)
  {
    loadMovie(link);
    currentPlaylistSong=0;
    el('playlist'+numMoviesInPlaylist).style.backgroundColor="#F9FAAA";
    currentSongID=id;
  }
  */
  
  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(playlistHandle==null)
    {
      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(){
  playlistHandle=null;
  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(){
  xmlHttp=newxmlrequest();
  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(){
  el("chatPane").scrollTop=el("chatPane").scrollHeight;
}

// Puts text in the chat.
function chat(txt)
{
  el("chatPane").innerHTML+="<span class='chat'>"+txt+"</span><br />";
  scrl();
}

