ARGV = [];
STDOUT = '';
STDIN = '';
$(function() {
	
	// capture commands and run them
	MouseApp.Terminal.prototype.onCommand = function(line) {
		STDOUT = '';
		ARGV = [];
		var term = this;
		$.each(line.split(';'), function(i,commandGroup) { // multiple commands
			$.each(commandGroup.split('|'), function(i,command) { // piped commands
				STDIN = STDOUT;
				term.execute(command); 
			});
			if(STDOUT.length) term.write(STDOUT+'\n');
		});
		TERM.scrollAllTheWayDown();
		return '';
  };
	
	MouseApp.Terminal.prototype.execute = function(line) {
		STDOUT = ''; 
		ARGV = this.extractArgs(line); // split on all non-quoted spaces
		var commands = Fwd.vfs['bin'];
		commands[ARGV[0]] ? commands[ARGV[0]].call(this, 'binary') : commands.commandMissing();
		return STDOUT;
	};
	
	MouseApp.Terminal.prototype.extractArgs = function(line) {
		var args = [];
		$.each(line.split('"'), function(i,v){
			v = $.trim(v)
			if(i%2) { if(v.length) args.push(v); }
			else {
				$.each(v.split(' '), function(i,v) {
					v = $.trim(v)
					if(v.length) args.push(v);
				});
			}
		});
		return args;
	};
	
	MouseApp.Terminal.prototype.onKeyTab = function() {
		var command = this.getCommand();
		var args = this.extractArgs(command);
		path = args[args.length-1];
		var newPath = autoComplete(path);
		var sc = command.split(' ');
		sc[sc.length-1] = newPath;
		var newCommand = sc.join(' ');
		this.clearCommand();
		this.write(newCommand);
	};
	
	// start a new terminal
	TERM = new MouseApp.Terminal($('#term'), {
		greeting: 'Loading welcome message...',
		columns: 112,
		indent: 0
	});
	
	// setup cookie support
	if($.cookie('history')) {
		var history = [];
		$.map($.cookie('history').split("\n"), function(c,i) {
			if(c && c.length) history.push(c);
		});
		TERM.history = history;
		TERM.backupNum = TERM.commandNum = TERM.historyNum = history.length;
	}
	var setHistory = function() { $.cookie('history', TERM.history.slice(-999).join("\n"), { expires: 30, path: '/' }); };
	$(window).unload(setHistory);
	$('#term').unload(setHistory);
	
	// show the welcome screen
	TERM.write(TERM.onCommand('clear'));
	TERM.write(TERM.onCommand('cat /etc/welcome.txt'));
	TERM.prompt();
});




Fwd = {};

Fwd.vfs = {};

Fwd.vfsCache = {};

Fwd.vfsHome = '/home/guest/';


Fwd.vfsFileType = function(path) {
	var pointer = typeof(path)=='string' ? Fwd.vfsPointer(path) : path;
	if(pointer==null) return null;
	if($.isFunction(pointer)) return 'file';
	else return 'dir';
};

Fwd.absolutePath = function(path) {
	if(!path || path=='') return Fwd.vfsCursor; // null or blank paths get passed straight through as the cursor
	var p = ''; 
	switch(path.charAt(0)) { 
		case '/' : // absolute path
			p = path;
			break;
		case '~' : // home path
			var d =	path.slice(1);
			if(d.charAt(0)=='/') d = d.slice(1);
			p = Fwd.vfsHome + d;
			break;
		default  : // relative path
			p = Fwd.vfsCursor + '/' + path;
	}
	var out = Fwd.expandPath(p);
	return out.length ? out : '/';
};

Fwd.expandPath = function(path) {
	var p = [];
	var ps = path.split('/');
	$.each(ps, function(i,v) {
		switch(v) {
			case '..': // up a level
			 	p.pop(); // take this element and the one above it
				break;
			case '.'  : // here
				break;
			case null: //useless
				break;
			case '': //useless
				break;
			default:
				p.push(v);
		};
	});
	var out = p.join('/');
	if(out.charAt(0)!='/') out = '/'+out;
	if(out.charAt(out.length-1)=='/') out = out.slice(0,-1);
	return out;
};

Fwd.vfsPointer = function(path) { // eg '/etc/help.txt'
	var path = path || Fwd.vfsCursor;
	path = Fwd.absolutePath(path);
	var p = path.split('/');
	var node = Fwd.vfs;
	try {
	$.each(p, function() {
		if(this && this.length) {
			if(node[this]) node = node[this];
			else throw "Missing VFS node";
		}
	});
	} catch(e) {
		return null
	};
	return node;
};

Fwd.vfsAutoComplete = function(userPath) {
	if(!userPath || userPath=='') return ''; // return if the path is empty
	var path = Fwd.absolutePath(userPath);
	var pointer = Fwd.vfsPointer(path);
	if(pointer!=null) { // make sure we don't have a valid path already
		return userPath;
	} else { // now we need to try traversing the tree
		var ps = path.split('/');
		var search = ps.pop();
		var newPath = ps.join('/');	
		var searchPath = (userPath.charAt(0)=='/' ? '/' : '') + newPath;
		var pointer = Fwd.vfsPointer(searchPath);	
		var match = search;
		$.each(pointer, function(f,c) {
			if(f.match(new RegExp('^'+search))) {
				match = f;
				return false;
			};
		});
		var newUserPath = userPath.replace(/[^\/]+$/,match);
		return newUserPath;
	}
};

//
// public methods
//

Fwd.vfsCursor = Fwd.vfsHome;

fileType = Fwd.vfsFileType;

filePointer = function(file, type) {
	var pointer = Fwd.vfsPointer(file);
	if(!type) return pointer;
	if(fileType(pointer)==type) return pointer;
	else throw file+': Not a '+(type=='dir' ? 'directory' : 'file')
};

cmd = function(line) {
	TERM.execute(line);
};

autoComplete = function(path) {
	return Fwd.vfsAutoComplete(path);
};

Fwd.File = function(action) {
	
	var load = function(path) {
		output = '';
		$.ajax({
			url 	: '/vfs'+path,
			async : false,
			dataType : 'text',
			success : function(ret) { output = ret },
			error : function(h,e,t) { throw "Failed to load data!\nPlease try again in a few minutes..." }
		});
		return output;
	};
	
	
	var loadWithCache = function(path) {
		if(!Fwd.vfsCache[path]) Fwd.vfsCache[path] = load(path);
		return Fwd.vfsCache[path];
	};
	
	return function(type) {
		output = '';
		try{
			switch(type) {
				case 'binary' : a = loadWithCache(action); eval(a); output = a; break;
				case 'text' : output = loadWithCache(action); break;
				case 'ln' : output = TERM.onCommand(action); break;
				default : output = action;
			}
		} catch(e) {
			STDOUT += '-'+ARGV[0]+': '+e;
		}
		return output;
	};
};
