var cmd = '';
var backscroll = '';
var prompt = 'guest@codemonkey.ws $ ';
var directories = {
  'blog' : 'http://blog.codemonkey.ws/',
  'flickr' : 'http://flickr.com/photos/aliguori/',
  'git' : 'http://git.codemonkey.ws/',
  'qemu' : 'http://www.qemu.org/',
  'resume' : "http://www.google.com/#sclient=&q=anthony+liguori+qemu",
  'work' : 'http://www.ibm.com/linux/ltc/',
  'contact' : 'mailto:anthony@codemonkey.ws'
};
var files = {
  'ABOUT' : "This is Anthony Liguori's home page.\n",
  'NEWS' : "12/9/2010 - Just set up this page.\n6/26/2011 - Restored server after EC2 crash.\n"
};
var cmd_history = new Array();
var history_index = 0;

var output_buffer;
function printf(value)
{
    output_buffer += value;
}

function in_array(array, elem)
{
    for (var i = 0; i < array.length; i++) {
        if (array[i] == elem) {
            return true;
        }
    }

    return false;
}

function cmd_ls(args)
{
    var first = true;

    for (var name in directories) {
        if (args.length > 1) {
            if (!(in_array(args, name) || in_array(args, name + '/'))) {
                continue;
            }
        }

        if (first) {
            first = false;
        } else {
            if (args.length == 1) {
                printf("  ");
            }
        }

        if (args.length > 1) {
            printf(name + ":\n\n");
        } else {
            printf(name +  "/");
        }
    }

    if (args.length > 1) {
        first = true;
    }

    for (var name in files) {
        if (args.length > 1 && !in_array(args, name)) {
            continue;
        }
        
        if (first) {
            first = false;
        } else {
            printf("  ");
        }
        printf(name);
    }
    
    if (!first) {
        printf("\n");
    }
}

function cmd_cat(args)
{
    if (args[1] in files) {
        printf(files[args[1]]);
    } else {
        printf("cat: " + args[1] + ": No such file or directory\n");
    }
}

function cmd_cd(args)
{
    if (args.length > 1) {
        dir = args[1];
        if (dir.substr(dir.length - 1, 1) == '/') {
            dir = dir.substr(0, dir.length - 1);
        }
        if (directories.hasOwnProperty(dir)) {
            window.location = directories[dir];
        } else {
            printf("File not found.\n");
        }
    }
}

function cmd_clear(args)
{
    backscroll = '';
    cmd = '';
}

function execute_command(command)
{
    var args = command.split(' ');
    var cmd_table = {
        'cat': cmd_cat,
        'ls': cmd_ls,
        'cd': cmd_cd,
        'clear': cmd_clear
    };
  
    output_buffer = '';
    if (args[0] in cmd_table) {
        cmd_table[args[0]](args);
    } else if (args[0] != '') {
        printf(args[0] + ": command not found\n");
    }
    return output_buffer;
}

function tab_options()
{
    var entries = new Array();

    for (var name in directories) {
        entries.push(name + '/');
    }

    for (var name in files) {
        entries.push(name);
    }

    return entries;
}

function tab_complete()
{
    if (cmd.length == 0) {
        return false;
    } else if (cmd.substr(cmd.length - 1, 1) == ' ') {
        return false;
    } else {
        var words, last, options;
        
        words = cmd.split(' ');
        last = words[words.length - 1];

        options = tab_options();
        for (var i = 0; i < options.length; i++) {
            if (options[i].substr(0, last.length) == last) {
                cmd += options[i].substr(last.length, options[i].length);
                return true;
            }
        }
    }

    return false;
}

var keydown_last_event;
var keydown_count = 0;
var keypress_event = 0;

function keydown(node, event)
{
    var ret = true;
    var keymap = {
        32: '  ',
        48: '0)', 49: '1!', 50: '2@', 51: '3#', 52: '4$', 53: '5%', 54: '6^',
        55: '7&', 56: '8*', 57: '9(',
        59: ';:', 61: '=+',

        65: "aA", 66: "bB", 67: "cC", 68: "dD", 69: "eE", 70: "fF", 71: "gG",
        72: "hH", 73: "iI", 74: "jJ", 75: "kK", 76: "lL", 77: "mM", 78: "nN",
        79: "oO", 80: "pP", 81: "qQ", 82: "rR", 83: "sS", 84: "tT", 85: "uU",
        86: "vV", 87: "wW", 88: "xX", 89: "yY", 90: "zZ",

        106: '**', 107: '++', 109: '-_', 111: '//', 
        188: ',<', 190: '.>',
        191: '/?', 192: '`~', 219: '[{', 220: '\\|', 221: ']}', 222: '\'\"'
    };

    switch (event.which) {
    case 8:
        if (cmd.length) {
            cmd = cmd.substr(0, cmd.length - 1);
        }
        break;
    case 9:
        tab_complete();
        ret = false;
        break;
    case 13:
        var output;
        backscroll += prompt + cmd + '\n';
        output = execute_command(cmd);
        backscroll += output;
        cmd_history.push(cmd);
        history_index = 0;
        cmd = '';
        break;
    case 38:
        cmd = cmd_history[cmd_history.length - 1 - history_index];
        history_index++;
        if (history_index > (cmd_history.length - 1)) {
            history_index = cmd_history.length - 1;
        }
        ret = false;
        break;
    case 40:
        cmd = cmd_history[cmd_history.length - 1 - history_index];
        history_index--;
        if (history_index < 0) {
            history_index = 0;
        }
        ret = false;
        break;
    default:
        if (event.which in keymap) {
            if (event.shiftKey) {
                cmd += keymap[event.which][1];
            } else {
                cmd += keymap[event.which][0];
            }
        } else if (event.which > 31) {
            cmd += '[' + event.which + ']';
        }
        break;
    }
    
    var value = backscroll + prompt + cmd;
    var lines = value.split('\n');
   
    if (lines.length > 25) {
        var first = true;
        value = '';
        for (var i = lines.length - 25; i < lines.length; i++) {
            if (first) {
                first = false;
            } else {
                value += '\n';
            }
            value += lines[i];
        }
    }
    
    node.value = value;
    
    if (!ret && event.preventDefault) {
        event.preventDefault();
    }

    keydown_count += 1;
    keydown_last_event = event;
    keypress_count = keydown_count;
    
    return ret;
}

function keypress(node, event)
{
    if (keydown_count < keypress_count) {
        keydown(node, keydown_last_event);
    }
    keypress_count += 1;
}

function start(node)
{
    node.value = backscroll + prompt;
    node.focus();
}

