// To do:
// Add html outputting to output all tags on the page
// Add sound with flash
// Add static and number spam for certain command

var blink = 0;  // Disables blinking cursor when 0
var busy = 0;	// Discerns whether or not to handle input
var typing = 0;	// The amount of time remaining in the last output operation
var curCmd = ""; // The currently running command
var hiddenText = ""; // For entering hidden text (e.g. passwords)
var inputFocus = { // An object that controls where to direct user input
	mainInput : "input.innerHTML",
	hiddenInput : "hiddenText",
	current : "input.innerHTML",
	main : function() {this.current=this.mainInput;},
	hidden : function() {this.current=this.hiddenInput;}
};
var cimage = new Image();
	cimage.src="cursor.bmp";
var display;
var input;
var screen;
var ajax_request = false;
window.onload=start;

function start() {
	display = document.getElementById("console_display");
	input = document.getElementById("console_input");
	blink=1;
	cursorblink("console_cursor");
	document.getElementById("pagebody").focus();
	
	// Create http request instance
    if (window.XMLHttpRequest) ajax_request = new XMLHttpRequest();
    else if (window.ActiveXObject) { // IE
		try {
			ajax_request = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
			try {
				ajax_request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {ajax_request = false;}
        }
    }
    if (!ajax_request) fail();

	// Handle backspaces (onkeydown is handled cross-browser for backspace)
	document.onkeydown=function(event) {
		if (window.event) event=window.event;
		
		var keyCode = event.charCode;
		if (keyCode == undefined || keyCode == 0) keyCode=event.keyCode;
		
		if (keyCode==8) {
			eval('if (busy==0) '+inputFocus.current+'='+inputFocus.current+'.substring(0, '+inputFocus.current+'.length-1);');
			return false;
		}
	};
	
	document.onkeypress=function(event) {
		if (window.event) event=window.event;
		
		var keyCode = event.charCode;
		if (keyCode == undefined || keyCode == 0) keyCode=event.keyCode;
		
		if (keyCode==27) { // Escape key
		}
		if (busy==0) {
			if (keyCode!=13) {
				if ((keyCode>62&&keyCode<127)||(keyCode==61)||(keyCode>38&&keyCode<60)||(keyCode>31&&keyCode<38)) {
					eval(inputFocus.current+'+=String.fromCharCode(keyCode);');
				}
			} else eval('doCmd(trim('+inputFocus.current+'))');
		}
	};
}

function fail() {
	output("Unauthorized access.", null, 1);
	setTimeout('output("<br>Connection terminated.", null, 1);', 1500);
	//setTimeout("", 3500); // play sound
	setTimeout('blink=0;document.getElementById("console_cursor").innerHTML="";display.innerHTML="";', 3700);
}

function ajaxPost(params) {
	var responseHandler = arguments.callee.caller.toString();
	responseHandler=responseHandler.substring(responseHandler.indexOf(' ')+1, responseHandler.indexOf('('));

	if (ajax_request.readyState == 0 || ajax_request.readyState == 4) {
		ajax_request.open("POST", "control.php", true);
		
		ajax_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		ajax_request.setRequestHeader("Content-length", params.length);
		ajax_request.setRequestHeader("Connection", "close");
		
		ajax_request.onreadystatechange = function() {
			if(ajax_request.readyState == 4 && ajax_request.status == 200) {
				eval(responseHandler + '("' + ajax_request.responseText + '");');
			}
		};
		
		ajax_request.send(params);
	}
}

function typeText(text, id, delay, clearBusy, currentChar) {
	if (currentChar==null) currentChar=1;
	typing=(text.substring(currentChar).length)*delay;
	if (currentChar<=text.length) {
		if (text.charAt(currentChar-1)=="<") {
			document.getElementById(id).innerHTML+=text.substring(currentChar-1, text.indexOf(">", currentChar-1)+1);
			currentChar=text.indexOf(">", currentChar-1)+2;
			typeText(text, id, delay, clearBusy, currentChar);
		} else if (text.charAt(currentChar-1)=="&") {
			document.getElementById(id).innerHTML+=text.substring(currentChar-1, text.indexOf(";", currentChar-1)+1);
			currentChar=text.indexOf(";", currentChar-1)+2;
			typeText(text, id, delay, clearBusy, currentChar);
		} else {
			document.getElementById(id).innerHTML+=text.substring(currentChar-1, currentChar);
			currentChar++;
			setTimeout("typeText('" + text + "', '" + id + "', " + delay + ", " + clearBusy + ", " + currentChar + ")", delay);
		}
	} else if (clearBusy==1) {
		busy=0;
	}
}

function cursorblink(id) {
	if (blink) {
		if (document.getElementById(id).innerHTML=="") document.getElementById(id).innerHTML="<img src=\"cursor.bmp\">";
		else document.getElementById(id).innerHTML="";
		setTimeout('cursorblink("'+id+'");',300);
	}
}

function trim(str) {
	return str.replace(/^\s+|\s+$/g, '');
}

function output(txt, clear, clearBusy) {
	if (typing>0) {
		setTimeout('output("' + txt + '", ' + clear + ', ' + clearBusy + ');', typing);
		return;
	}
	busy=1;
	if (clear!=null) {
		typeText(txt, "console_display", 10);
		setTimeout("display.innerHTML='';busy=0;", txt.length+clear);
	} else {
		if (clearBusy==null) typeText(txt, "console_display", 10, 1);
		else typeText(txt, "console_display", 10);
	}
}

function auth(response, usr, pwd) {
	if (response==null) {
		output(((curCmd!="") ? "<br />" : "") + "auth: authenticating... ", null, 1);
		ajaxPost("requestType=auth&usr="+escape(encodeURI(usr))+"&pwd="+escape(encodeURI(pwd)));
	} else {
		if (response=="0") {
			output("<br />auth: access granted<br />");
			getMotd();
		} else if (response=="1") output("<br />auth: access denied<br />");
		else output("<br />auth: error<br />");
		curCmd="";
		inputFocus.main();
	}
}

function create(response, args) {
	if (response==null) {
		switch (args[1].toLowerCase()) {
			case "game":
				if (args.length<4) output("create: you must supply a name and status to create a game<br />");
				else ajaxPost("requestType=createGame&gameName="+escape(encodeURI(args[2]))+"&gameStatus="+escape(encodeURI(args[3])));
				break;
			default:
				output("create: invalid content type \"" + args[1] + "\"<br />");
		}
	} else {
		if (response=="0") output("create: created successfully<br />");
		else if (response=="1") output("create: access denied<br />");
		else output("create: error<br />");
	}
}

function getVer(response) {
	if (response==null) ajaxPost("requestType=ver");
	else output("ver: " + response + "<br />");
}

function getMotd(response) {
	if (response==null) ajaxPost("requestType=motd");
	else output("motd: " + response + "<br />");
}

function doCmd(cmd) {
	eval(inputFocus.current+'="";');
	if (curCmd!="") cmd=curCmd+" "+cmd;
	var args=cmd.split(' ');
	for (var i = 0; i < args.length; i++) {
		if (args[i].charAt(0)=="\"") {
			args[i]=args[i].substring(1);
			var found = false;
			for (var j = i; j < args.length; j++) {
				var currentIndex = args[j].indexOf('"');
				while (currentIndex != -1) {
					if (args[j].charAt(currentIndex-1) == "\\") currentIndex = args[j].indexOf('"', currentIndex+1);
					else {
						if (currentIndex != (args[j].length - 1)) {
							if (j!=i) {
								args[i]+=(" "+args[j].substring(0, currentIndex));
								args[j]=args[j].substring(currentIndex+1);
							} else {
								args.splice(i+1, 0, args[i].substring(currentIndex+1));
								args[i]=args[i].substring(0, currentIndex);
							}
						} else {
							if (j!=i) {
								args[i]+=(" "+args[j].substring(0, args[j].length-1));
								args.splice(j, 1);
								j--;
							} else args[i]=args[i].substring(0, args[i].length-1);
						}
						found=true;
						break;
					}
				}
				if (found) break;
				else {
					if (j!=i) {
						args[i]+=(" "+args[j]);
						args.splice(j, 1);
						j--;
					}
				}
			}
		}
		args[i]=args[i].replace(/\\\"/gi, "\"");
	}
	switch(args[0].toLowerCase()) {
		case "auth":
			if (args.length<2) output("auth: this command requires at least one argument<br />");
			else if (args.length>=3) auth(null, args[1], args[2]);
			else if (args.length==2) {
				curCmd="auth " + args[1];
				output("auth: password for "+args[1]+": ");
				inputFocus.hidden();
			}
			break;
		case "version":
		case "ver":
			getVer();
			break;
		case "news":
		case "motd":
			getMotd();
			break;
		case "create":
			if (args.length<3) output("create: this command requires at least two arguments<br />");
			else create(null, args);
			break;
		case "projects":
			alert("rawrawrawr");
		case "games":
			alert("rawrawrawrawr");
		case "cls":
			display.innerHTML="";
			break;
		default:
			output("Unknown command: " + args[0] + "<br />");
	}
}
