var MAX_ROW = 30;
var BLANK = "&nbsp;";

var BLACK   = 0;
var RED     = 1;
var GREEN   = 2;
var YELLOW  = 3;
var BLUE    = 4;
var MAGENTA = 5;
var CYAN    = 6;
var WHITE   = 7;

var COLOR_0 = "#000000";
var COLOR_1 = "#660000";
var COLOR_2 = "#006600";
var COLOR_3 = "#FF9900";
var COLOR_4 = "#000066";
var COLOR_5 = "#990066";
var COLOR_6 = "#009999";
var COLOR_7 = "#999999";

var BRIGHT_COLOR_0 = "#666666";
var BRIGHT_COLOR_1 = "#FF0000";
var BRIGHT_COLOR_2 = "#00FF00";
var BRIGHT_COLOR_3 = "#FFFF00";
var BRIGHT_COLOR_4 = "#0000FF";
var BRIGHT_COLOR_5 = "#FF3399";
var BRIGHT_COLOR_6 = "#66FFFF";
var BRIGHT_COLOR_7 = "#FFFFFF";


function Console(elementName) {

    this.row = 1;
    this.col = 1;
    this.colorBright = false;
    this.backgroundBright = false;
    this.fgColor = WHITE;
    this.bgColor = BLACK;
    this.timeoutId = null;
    this.connected = false;
    
    this.consoleElement = document.getElementById(elementName);
    var contents = "";
    for (var i = 0; i < MAX_ROW; i++) {
        contents += "<div id=\"row" + (i+1) + "\">";
        for (var j = 0; j < 80; j++) {
            contents += "<span>" + BLANK + "</span>";
        }
        contents += "</div>";
    }
    this.consoleElement.innerHTML = contents;

}

Console.prototype.clear = function() {

    for (var i = 1; i <= MAX_ROW; i++) {
    
        var r = document.getElementById("row" + i);
        for (var j = 0; j < 80; j++) {
            var c = r.childNodes[j];
            c.style.color = this.getForegroundColor();
            c.style.backgroundColor = this.getBackgroundColor();
            c.innerHTML = BLANK;
        }
        
    }
        	
    this.row = 1;
    this.col = 1;

}

Console.prototype.ansi = function(cmd) {

    var command = "";
    var params = "";
    
    if (cmd.length > 0) {
		command = cmd.substring(cmd.length - 1);
		params = cmd.substring(0, cmd.length - 1);
	}
	
	var paramArray = params.split(";");
	
    if (command == "A") {
        var x = Number(params);
        this.row = this.row - x;
        if (this.row < 1) row = 1;
    } else    
    if (command == "B") {
        var x = Number(params);
        this.row = this.row + x;
        if (this.row > MAX_ROW) row = 30;
    } else
    if (command == "C") {
        var x = Number(params);
        this.col = this.col + x;
        if (this.col > 80) this.col = 80;
    } else
    if (command == "D") {
        var x = Number(params);
        this.col = this.col - x;
        if (this.col < 1) this.col = 1;
    } else    
    if (command == "E") {
        var x = Number(params);
        this.row = this.row + x;
		this.addNewRows();
    } else    
    if (command == "F") {
        var x = Number(params);
        this.row = this.row - x;
        if (this.row < 1) this.row = 1;
    } else
    if (command == "H" || command == "f") {
        var newRow = 1;
        var newCol = 1;
        if (paramArray.length >= 1) {
            var tempRow = paramArray[0];
            if (tempRow == "") {
                tempRow = 1;
            }
            newRow = Number(tempRow);
        }
        if (paramArray.length >= 2) {
            var tempCol = paramArray[1];
            if (tempCol == "") {
                tempCol = 1;
            }
            newCol = Number(tempCol);
        }
		this.row = newRow;
		this.col = newCol;
		this.addNewRows();
    } else    
    if (command == "J") {
    
        var clearType = 0;
        if (params == "0") {
            // clear from cursor to end of screen (row 30, column 80)
            var r = document.getElementById("row" + this.row);
            for (var i = this.col; i < 81; i++) {
                var c = r.childNodes[i - 1];
				c.style.color = this.getForegroundColor();
				c.style.backgroundColor = this.getBackgroundColor();
       		    c.innerHTML = BLANK;
       		}
       		for (var i = this.row + 1; i <= MAX_ROW; i++) {
	   	        var r = document.getElementById("row" + i);
	   	        for (var j = 0; j < 80; j++) {
	        	    var c = r.childNodes[j];
					c.style.color = this.getForegroundColor();
					c.style.backgroundColor = this.getBackgroundColor();
        		    c.innerHTML = BLANK;
        		}
       		}
        } else if (params == "1") {
            // clear from cursor to row 1, col 1 (backwards)
            var r = document.getElementById("row" + this.row);
            for (var i = this.col; i > 0; i--) {
                var c = r.childNodes[i - 1];
				c.style.color = this.getForegroundColor();
				c.style.backgroundColor = this.getBackgroundColor();
       		    c.innerHTML = BLANK;
       		}
       		for (var i = this.row - 1; i > 0; i--) {
	   	        var r = document.getElementById("row" + i);
	   	        for (var j = 0; j < 80; j++) {
	        	    var c = r.childNodes[j];
					c.style.color = this.getForegroundColor();
					c.style.backgroundColor = this.getBackgroundColor();
        		    c.innerHTML = BLANK;
        		}
       		}
        } else if (params == "2") {
            // clear screen, move cursor to row 1, col 1
            this.clear();
        }
    
    } else
    if (command == "K") {
        
        if (params == "" || params == "0") {
        	// clear from cursor to end of line
            var r = document.getElementById("row" + this.row);
            for (var i = this.col; i < 81; i++) {
                var c = r.childNodes[i - 1];
				c.style.color = this.getForegroundColor();
				c.style.backgroundColor = this.getBackgroundColor();
       		    c.innerHTML = BLANK;
       		}
        } else if (params == "1") {
        	// clear from cursor to beginning of line
            var r = document.getElementById("row" + this.row);
            for (var i = this.col; i > 0; i--) {
                var c = r.childNodes[i - 1];
				c.style.color = this.getForegroundColor();
				c.style.backgroundColor = this.getBackgroundColor();
       		    c.innerHTML = BLANK;
       		}
        } else if (params == "2") {
        	// clear entire line
            var r = document.getElementById("row" + this.row);
            for (var i = 0; i < 80; i++) {
                var c = r.childNodes[i];
				c.style.color = this.getForegroundColor();
				c.style.backgroundColor = this.getBackgroundColor();
       		    c.innerHTML = BLANK;
       		}
        
        } else {
            console.log("unsupported K parameter " + params);
        }
        
    } else    
    if (command == "S") {
        //alert("scroll up");
    } else    
    if (command == "T") {
        //alert("scroll down");
    } else
	if (command == "m") {
	    if (paramArray.length == 0) {
	        this.fgColor = WHITE;
	        this.bgColor = BLACK;
	        this.colorBright = false;
	        this.backgroundBright = false;
	    } else {
	        for (var i = 0; i < paramArray.length; i++) {
	            var p = Number(paramArray[i]);
				if (p == 0) {
					this.colorBright = false;
                    this.backgroundBright = false;
					this.fgColor = WHITE;
					this.bgColor = BLACK;
				} else if (p == 1) {
	            	this.colorBright = true;
				} else if (p == 22) {
	            	this.colorBright = false;
	            } else if (p >= 30 && p <= 37) {
       	            this.fgColor = p - 30;
				} else if (p >= 40 && p <= 47) {
    	            this.bgColor = p - 40;
				}
	        }
	    }
	} else
	if (command == "Z" && params == "99") {
	    this.connected = false;
	    document.onkeypress = null;
	} else {
	    console.log("unhandled command: " + cmd);
	}

}

Console.prototype.write = function(text) {

	var ansiBuf = "";
	var escSeq = false;
	var escSeqCounter = 0;

    for (var j = 0; j < text.length && this.connected; j++) {

        var temp = text.charAt(j);
        var code = text.charCodeAt(j);
        
		if (escSeq) {
		
			// we've already seen an ESC
			if (escSeqCounter == 1) {
				if (temp == "[") {
					escSeqCounter++;
				} else {
					escSeq = false;
				}
			} else {
				ansiBuf += temp;
				escSeqCounter++;
				if (code >= 64 && code <= 126) {
					escSeq = false;
					this.ansi(ansiBuf);
					ansiBuf = "";
				}
			}
			
		} else {
					
			if (code == 27) {
			    temp = "";
				// begin ANSI escape sequence
				escSeq = true;
				escSeqCounter = 1;
			} else if (temp == ' ') {
    	        temp = BLANK;
    	    } else if (temp == '<') {
    	        temp = "&lt;";
    	    } else if (temp == '>') {
    	        temp = "&gt;";
    	    } else if (code == 8) {
    	        temp = "";
    	        this.col--;
	        } else if (temp == '\n') {
    	        temp = "";
        	    this.row++;
            	this.col = 1;
	            this.addNewRows();
    	    } else if (code > 127) {
    	        temp = "&#" + code + ";";
    	    } else if (code < 32) {
    	        temp = "";
    	    }
				
	        if (temp != "") {
        
    	        var r = document.getElementById("row" + this.row);
        	    var c = r.childNodes[this.col - 1];
				c.style.color = this.getForegroundColor();
				c.style.backgroundColor = this.getBackgroundColor();
        	    c.innerHTML = temp;
	            this.col++;

    	        if (this.col > 80) {
        	        this.row++;
            	    this.col = 1;
                	this.addNewRows();
	            }
            
    	    }

		}

    }

    if (this.connected) {
        var self = this;
        this.timeoutId = window.setTimeout(function() { self.sendData(); }, 1000);
    } else {
        window.clearTimeout(this.timeoutId);
    }

}

Console.prototype.addNewRows = function() {

    if (this.row > MAX_ROW) {
    
        var howMany = this.row - MAX_ROW;
        for (var z = 0; z < howMany; z++) {
    
            var rows = this.consoleElement.childNodes;
            for (var i = 0; i < rows.length; i++) {
                var rowId = Number(rows[i].id.substring(3));
                rowId--;
                rows[i].id = "row" + rowId;
                if (rowId < 1) {
                    rows[i].style.display = "none";
                }
            }
            var newRow = document.createElement("DIV");
            var spans = "";
            for (var j = 0; j < 80; j++) {
                spans += "<span onclick=\"whereAmI(this);\">" + BLANK + "</span>";
            }
            newRow.id = "row" + MAX_ROW;
            newRow.innerHTML = spans;
            this.consoleElement.appendChild(newRow);
        
        }
    
        this.row = 30;
    
    }

}

Console.prototype.sendData = function(c, k) {

    window.clearTimeout(this.timeoutId);

    var url = "console";
    var httpRequest = getHttpRequest();

    if (!c) c = 0;
    if (!k) k = 0;
    
    var game = "";
/*
    if (!this.connected) {
        var lord = document.getElementById("lord");
        var fe = document.getElementById("fe");
        if (lord.checked) {
            game = "&game=LORD";
        } else {
            game = "&game=FE";
        }
    }
*/
    
    if (httpRequest) {
        var tempCon = this;
        httpRequest.onreadystatechange = function() { tempCon.processResponse(httpRequest); };
        if (httpRequest.overrideMimeType) {
            httpRequest.overrideMimeType('text/plain');
        }
        httpRequest.open('POST', url, true);
        httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        httpRequest.send("c=" + c + "&k=" + k);
    }

}

Console.prototype.processResponse = function(httpRequest) {

    if (httpRequest.readyState == 4) {
        if (httpRequest.status == 200) {
        
            this.connected = true;
            this.write(httpRequest.responseText);
            
        } else {
            console.log("There was a problem with the request!");
        }
    }

}

Console.prototype.getBackgroundColor = function() {

    if (this.backgroundBright) {
        return eval("BRIGHT_COLOR_" + this.bgColor);
    } else {
        return eval("COLOR_" + this.bgColor);
    }

}

Console.prototype.getForegroundColor = function() {

    if (this.colorBright) {
        return eval("BRIGHT_COLOR_" + this.fgColor);
    } else {
        return eval("COLOR_" + this.fgColor);
    }

}
