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 control panel
        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 response received, 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);
        }
    }
};
