rconsTerm = function(nodeName, height, width) {
	var sid = nodeName;
	var keyBuf = [];
	var receivingFlag = false;
	var sendTimeout = "";
	var errorTimeout = "";
	var queryStable = 's=' + sid + '&w=' + height + '&h=' + width + '&c=1&k=';
	var maxDelay = 200;
	var firstFlag = true;

	var workingStatus = "";
	var termArea = "";
	var errorArea = "";

	var ie = 0;
	if (window.ActiveXObject) {
		ie = 1;
	}

	rconsInit();
	// init
	function rconsInit() {
		// create status, configure the css
		workingStatus = $('<span>.</span>');
		workingStatus.attr('class', 'off');

		// create the disconnect button
		var disconnectButton = $('<a class="off">Disconnect</a>');
		disconnectButton.bind('click', function() {
			window.close();
		});

		// create the control panel, add to the rcons div
		var controlPanel = $('<pre class="stat"></pre>');
		$('#term').append(controlPanel);

		// create the error erea
		errorArea = $('<span></span>');

		// add all item to controlPanel
		controlPanel.append(workingStatus);
		controlPanel.append(disconnectButton);
		controlPanel.append(errorArea);

		// create the termArea
		termArea = $('<div></div>');
		$('#term').append(termArea);

		// bind keypress event
		document.onkeypress = rconsKeypress;
		document.onkeydown = rconsKeydown;
		window.onbeforeunload = function() {
			rconsDisconnect();
			alert("Closing remote console");
		};

		rconsSend();
	}

	// close the connection
	function rconsDisconnect() {
		window.clearTimeout(sendTimeout);
		window.clearTimeout(errorTimeout);

		$.ajax({
			type : "POST",
			url : "lib/rcons.php",
			data : queryStable + '&q=1',
			dataType : 'json'
		});
	}

	// translate the key press
	function rconsKeypress(event) {
		if (!event)
			var event = window.event;
		var kc = "";
		var k = "";
		if (event.keyCode)
			kc = event.keyCode;
		if (event.which)
			kc = event.which;
		if (event.altKey) {
			if (kc >= 65 && kc <= 90)
				kc += 32;
			if (kc >= 97 && kc <= 122) {
				k = String.fromCharCode(27) + String.fromCharCode(kc);
			}
		} else if (event.ctrlKey) {
			if (kc >= 65 && kc <= 90)
				k = String.fromCharCode(kc - 64); // Ctrl-A..Z
			else if (kc >= 97 && kc <= 122)
				k = String.fromCharCode(kc - 96); // Ctrl-A..Z
			else if (kc == 54)
				k = String.fromCharCode(30); // Ctrl-^
			else if (kc == 109)
				k = String.fromCharCode(31); // Ctrl-_
			else if (kc == 219)
				k = String.fromCharCode(27); // Ctrl-[
			else if (kc == 220)
				k = String.fromCharCode(28); // Ctrl-\
			else if (kc == 221)
				k = String.fromCharCode(29); // Ctrl-]
			else if (kc == 219)
				k = String.fromCharCode(29); // Ctrl-]
			else if (kc == 219)
				k = String.fromCharCode(0); // Ctrl-@
		} else if (event.which == 0) {
			if (kc == 9)
				k = String.fromCharCode(9); // Tab
			else if (kc == 8)
				k = String.fromCharCode(127); // Backspace
			else if (kc == 27)
				k = String.fromCharCode(27); // Escape
			else {
				if (kc == 33)
					k = "[5~"; // PgUp
				else if (kc == 34)
					k = "[6~"; // PgDn
				else if (kc == 35)
					k = "[4~"; // End
				else if (kc == 36)
					k = "[1~"; // Home
				else if (kc == 37)
					k = "[D"; // Left
				else if (kc == 38)
					k = "[A"; // Up
				else if (kc == 39)
					k = "[C"; // Right
				else if (kc == 40)
					k = "[B"; // Down
				else if (kc == 45)
					k = "[2~"; // Ins
				else if (kc == 46)
					k = "[3~"; // Del
				else if (kc == 112)
					k = "[[A"; // F1
				else if (kc == 113)
					k = "[[B"; // F2
				else if (kc == 114)
					k = "[[C"; // F3
				else if (kc == 115)
					k = "[[D"; // F4
				else if (kc == 116)
					k = "[[E"; // F5
				else if (kc == 117)
					k = "[17~"; // F6
				else if (kc == 118)
					k = "[18~"; // F7
				else if (kc == 119)
					k = "[19~"; // F8
				else if (kc == 120)
					k = "[20~"; // F9
				else if (kc == 121)
					k = "[21~"; // F10
				else if (kc == 122)
					k = "[23~"; // F11
				else if (kc == 123)
					k = "[24~"; // F12
				if (k.length) {
					k = String.fromCharCode(27) + k;
				}
			}
		} else {
			if (kc == 8)
				k = String.fromCharCode(127); // Backspace
			else
				k = String.fromCharCode(kc);
		}
		if (k.length) {
			if (k == "+") {
				rconsQueue("%2B");
			} else {
				rconsQueue(escape(k));
			}
		}
		event.cancelBubble = true;
		if (event.stopPropagation)
			event.stopPropagation();
		if (event.preventDefault)
			event.preventDefault();
		return false;
	}

	// translate the key press, same with rconsKeypress
	function rconsKeydown(event) {
		if (!event)
			var event = window.event;
		if (ie) {
			o = {
				9 : 1,
				8 : 1,
				27 : 1,
				33 : 1,
				34 : 1,
				35 : 1,
				36 : 1,
				37 : 1,
				38 : 1,
				39 : 1,
				40 : 1,
				45 : 1,
				46 : 1,
				112 : 1,
				113 : 1,
				114 : 1,
				115 : 1,
				116 : 1,
				117 : 1,
				118 : 1,
				119 : 1,
				120 : 1,
				121 : 1,
				122 : 1,
				123 : 1
			};
			if (o[event.keyCode] || event.ctrlKey || event.altKey) {
				event.which = 0;
				return keypress(event);
			}
		}
	}

	// send the command and request to server
	function rconsSend() {
		var keyPressList = '';
		var requireString = '';
		if (receivingFlag) {
			return;
		}

		receivingFlag = true;
		workingStatus.attr('class', 'on');

		while (keyBuf.length > 0) {
			keyPressList += keyBuf.pop();
		}

		if (firstFlag) {
			requireString = queryStable + keyPressList + '&f=1';
			firstFlag = false;
		} else {
			requireString = queryStable + keyPressList;
		}

		$.ajax({
			type : "POST",
			url : "lib/rcons.php",
			data : requireString,
			dataType : 'json',
			success : function(data) {
				rconsUpdate(data);
			}
		});

		errorTimeout = window.setTimeout(rconsSendError, 15000);

	}

	// when receive the response, update the term area
	function rconsUpdate(data) {
		window.clearTimeout(errorTimeout);
		errorArea.empty();
		if (data.term) {
			termArea.empty().append(data.term);
			maxDelay = 200;
		} else {
			maxDelay = 2000;
		}

		receivingFlag = false;
		workingStatus.attr('class', 'off');
		sendTimeout = window.setTimeout(rconsSend, maxDelay);
	}

	function rconsSendError() {
		workingStatus.attr('class', 'off');
		errorArea.empty().append('Send require error.');
	}

	function rconsQueue(kc) {
		keyBuf.unshift(kc);
		if (false == receivingFlag) {
			window.clearTimeout(sendTimeout);
			sendTimeout = window.setTimeout(rconsSend, 1);
		}
	}
};