var codeWin;

String.prototype.trim = function() {
	var startPos, endPos;
	for (startPos = new Number(0); startPos < this.length; startPos++) {
    	if (this.charAt(startPos) != ' ' && this.charAt(startPos) != '\n' && this.charAt(startPos) != '\r') {
	    	break;
    	}
	}
	if (startPos == this.length) return "";
	for (endPos = new Number(this.length - 1); endPos >= 0; endPos--) {
    	if (this.charAt(endPos) != ' ' && this.charAt(endPos) != '\n' && this.charAt(endPos) != '\r') {
	    	endPos++;
	    	break;
    	}
	}
	//alert(startPos.toString()+", "+endPos.toString());
	return this.slice(startPos, endPos);
}
/* Is this a number?
 */
function isNumber(thisStr) {
	var i;
	var isHex = false;
	
	for (i = 0; i < thisStr.length; i++) {
		switch (thisStr.charAt(i)) {
			case "0":
			case "1":
			case "2":
			case "3":
			case "4":
			case "5":
			case "6":
			case "7":
			case "8":
			case "9":
			break;
			
			case "A":
			case "B":
			case "C":
			case "D":
			case "E":
			case "F":
			if (!isHex) return false;
			break;
			
			case "x":
			    if (thisStr.slice(0, 2) == "0x") {
				    isHex = true;
			    } else return false;
			break;
			
			default:
			return false;
			break;
		}
	}
	return true;
}

/* Executes cout statements
 */
function runCout(thisCode) {
	var myLine, myLines, myBit, myBits, i, j;
	var thisSpan;
	
	myLines = thisCode.split(";");
	for (i = 0; i < myLines.length; i++) {
		myLine = new String(myLines[i]);
		myLine = myLine.trim();
		
		//alert("\""+myLine+"\"");
		
		if (myLine != "" && myLine != null) {
			myBits = myLine.split("<<");
			myBit = new String(myBits[0]);
			myBit = myBit.trim();
			
			//alert(myBit);
			
			if (myBit != "cout") {
				var thisSpan = codeWin.document.createElement("span");
				thisSpan.style.backgroundColor = "#ff0000";
				thisSpan.innerHTML = "(Unrecognized line " + myLine + ".)";
				codeWin.document.body.appendChild(thisSpan);
			} else {
				for (j = 1; j < myBits.length; j++) {
					myBit = new String(myBits[j]);
					myBit = myBit.trim();
					
					var thisSpan = codeWin.document.createElement("span");
					
					if (myBit == "") {
						thisSpan.innerHTML = "";
					} else if (myBit == "endl") {
						thisSpan.innerHTML = "<br>";
					} else if (myBit.charAt(0) == "\"" && myBit.charAt(myBit.length-1) == "\"") {
					    thisSpan.innerHTML =  myBit.slice(1, myBit.length-1);
				    } else if (myBit.indexOf("+") != -1 || myBit.indexOf("-") != -1 || myBit.indexOf("*") != -1
				        || myBit.indexOf("/") != -1) {
					    thisSpan.innerHTML = eval(myBit);
					} else if (isNumber(myBit)) {
						thisSpan.innerHTML = myBit;
				    } else {
					    thisSpan.style.backgroundColor = "#ff0000";
					    thisSpan.innerHTML = "(Unrecognized bit " + myBit + ")";
					    //thisSpan.innerHTML = myBit;
				    }
					
				    if (thisSpan.innerHTML != "") {
				    	codeWin.document.body.appendChild(thisSpan);
			    	}
				    
					delete myBit;
				}
				delete myLine;
			}
		}
	}
}

/* Performs a line-by-line execution of the given code using the given document.
 */
function runCode(thisCode, thisDoc) {
	var myCmdLine, myStart = 0, myEnd = 0;
	
	var newCode = thisCode.replace(/\n/g, "\\\n");
    newCode = newCode.replace(/\r/g, "");
	
    myStart = 0;
	myEnd = thisCode.indexOf(";", 1);
	myCmdLine = new String(thisCode.slice(myStart, myEnd).trim());
	while (myCmdLine != "") {
		alert("Command Line: "+myCmdLine);
	
		// Get command
		var t = new Number(myCmdLine.length);
		var v = new Number(myCmdLine.indexOf("("));
		var cmdtype = 0;
		/* Command types:
		 * 0 - None
		 * 1 - Function call
		 * 2 - Stream
		 */
		
		if (v < t) { t = v; cmdtype = 1; }
		
		v = myCmdLine.indexOf("<<");
		alert(v);
		if (v < t) { t = v; cmdtype = 2; }
		
		v = myCmdLine.indexOf(" ");
		alert(v);
		if (v < t) { t = v;}
		
		var myCmd = myCmdLine.slice(0, t).trim();
		var myArgs = myCmdLine.slice(t).trim();
		var myBits;
		
		// Determine what command is.
		thisDoc.body.innerHTML = thisDoc.body.innerHTML.concat("(Beginning of output:)");
		alert(cmdtype);
		switch (cmdtype) {
			case 2:
			    myBits = myArgs.split("<<");
			    
			    var i, myBit;
			    for (i = 1; i < myBits.length; i++) {
				    myBit = new String(myBits[i]);
				    myBit = myBit.trim();
				    
				    if (myBit.charAt(0) == "\"" && myBit.charAt(myBit.length-1) == "\"") {
					    thisDoc.body.innerHTML.concat(myBit);
				    } else if (myBit.indexOf("+") + myBit.indexOf("-") + myBit.indexOf("*")
				        + myBit.indexOf("/") != 0) {
					    thisDoc.body.innerHTML.concat(myBit);
				    } else {
					    thisDoc.body.innerHTML.concat("<br>(Invalid bit: " + myBit + ")");
				    }
			    }
			break;
			
			case 1:
			    myBits = myArgs.split(",");
			    if (myCmd == "system") {
				    if (myBits.length != 1) {
					    thisDoc.body.innerHTML.concat("<br>(Too many arguments to system())<br>");
				    } else {
					    switch (myBits[0]) {
						    case "PAUSE":
						    thisDoc.body.innerHTML.concat("<br>Press any key to continue . . .");
						    break;
						    
						    case "GDC":
						    thisDoc.body.innerHTML.concat("<br>GDC Rocks!");
						    break;
					    }
					}
			    }
			break;
			
			default:
			    thisDoc.body.innerHTML.concat("<br>(Unrecognized command: " + myCmdLine + ")");
			break;
		}
		
		myStart = myEnd + 1;
		myEnd = thisCode.indexOf(";", myStart);
		myCmdLine = new String(thisCode.slice(myStart, myEnd).trim());
	}
}

/* Makes an execution window with the given code.
 */
function makeWin(thisCode) {    
    var runWin = window.open("interp.htm", "Console", "width=600, height=400");
    if (runWin) {
	    codeWin = runWin;
	    alert("Press [OK] to start!");
	    runCout(thisCode);
	    runWin.focus();
	    //runCout(thisCode, runWin.document);
	}
}