var CONSOLE_MAX_LINES = 16;
var CONSOLE_MAX_COLS = 90;

var CMD_HELP = 'help';
var CMD_SHOW = 'show';
var CMD_SHOWVARS = 'showvars';
var CMD_SHOWFLAGS = 'showflags';
var CMD_SHOWOBJS = 'showobjs';
var CMD_INVENTORY = 'inventory';
var CMD_CLEAR = 'clear';
var CMD_DEBUG = 'debug';

var console = {
	// the element that represents the console
	el: null,
	// the element that represents the cursor
	cursor: null,
	lines: new Array( CONSOLE_MAX_LINES ),
	// the line where commands are given
	prompt: '&gt;',
	// the prompt symbol
	PS1: '&gt;',
	active: false,
	
	toggle: function()
	{
		if ( this.active )
		{
			this.el.style.visibility = 'hidden';
		}
		else
		{
			this.draw();
			this.el.style.visibility = 'visible';
		}
		
		this.active = !this.active;
	}
	,
	handleKey: function( e )
	{
		if ( e.keyCode == KEY_BACKSPACE )
		{
			// remember the else...
			if ( this.prompt != this.PS1 )
			{
				this.prompt = this.prompt.substr( 0, this.prompt.length-1 );
			}
		}
		else if ( e.keyCode == KEY_ENTER )
		{
			this.output( this.prompt );
			this.parseInput();
			this.prompt = this.PS1;
		}
		else
		{
			var c = String.fromCharCode( e.charCode ).toLowerCase();
			this.prompt += c;
		}
		this.draw();
	}
	,
	draw: function()
	{
		this.el.innerHTML = '<pre>' + this.lines.join( "&nbsp;\n" ) 
							+ "\n" + this.prompt + '_</pre>';
	}
	,
	parseInput: function()
	{
		var input = this.prompt.substr( this.PS1.length );
		input = input.split( /\s+/ );
		
		switch ( input[0] )
		{
			case CMD_SHOW:
				for ( var i = 1; i < input.length; i++ )
				{
					this.show( input[i] );
				}
				break;
				
			case CMD_SHOWVARS:
				this.showVars( parseInt(input[1]), parseInt(input[2]) );
				break;
				
			case CMD_SHOWFLAGS:
				this.showFlags( parseInt(input[1]), parseInt(input[2]) );
				break;
				
			case CMD_SHOWOBJS:
				this.showObjects( parseInt(input[1]), parseInt(input[2]) );
				break;
			
			case CMD_INVENTORY:
				this.inventory();
				break;
			
			case CMD_DEBUG:
				this.debug( input );
				break;
				
			case CMD_CLEAR:
				this.clear();
				break;
				
			case CMD_HELP:
				this.help();
				break;
				
			case '':
				// do nothing
				break;
				
			default:
				if ( !parse_agi_command( input.join( ' ' ) ) )
				{
					this.output( MSG_UNKNOWN_CMD + ': ' + input[0] )
				}
				break;
		}
	}
	,
	show: function( arg )
	{
		var number = parseInt( arg.substr( 1 ) );
		switch ( arg.charAt(0) )
		{
			case 'v':
				this.output( arg + ': ' + $v[number] );
				break;
			
			case 'f':
				this.output( arg + ': ' + $f[number] );
				break;
			
			case 'o':
				this.output( arg + ': ' + $o[number].toString() );
				break;
		}
	}
	,
	showVars: function( start, end )
	{
		var s = '';
		var a;
		
		if ( !start || start < 0 ) { start = 0; }
		if ( !end || end >= $v.length ) { end = $v.length-1; }
		
		for ( var i = start; i <= end; i++ )
		{
			a = 'v' + i + ': ' + $v[i] + '|';
			// when the buffer can't hold any more chars then flush it to the console
			if ( s.length + a.length > CONSOLE_MAX_COLS )
			{
				this.output( s );
				s = '';
			}
			s += a;
		}
		
		// output the last chars in the buffer
		if ( s.length > 0 )
		{
			this.output( s );
		}
	}
	,
	showFlags: function( start, end )
	{
		var s = '';
		var a;
		
		if ( !start || start < 0 ) { start = 0; }
		if ( !end || end >= $f.length ) { end = $f.length-1; }
		
		for ( var i = start; i <= end; i++ )
		{
			a = 'f' + i + ': ' + $f[i] + '|';
			// when the buffer can't hold any more chars then flush it to the console
			if ( s.length + a.length > CONSOLE_MAX_COLS )
			{
				this.output( s );
				s = '';
			}
			s += a;
		}
		// ouput the last chars in the buffer
		if ( s.length > 0 )
		{
			this.output( s );
		}
	}
	,
	showObjects: function( start, end )
	{
		var s = '';
		var a;
		
		if ( !start || start < 0 ) { start = 0; }
		if ( !end || end >= $o.length ) { end = $o.length-1; }
		
		for ( var i = start; i <= end; i++ )
		{
			// show only on screen objects
			if ( !$o[i].on_screen )
			{
				continue;
			}
			
			a = 'o' + i + ': ' + $o[i].toString() + ' ';
			// when the buffer can't hold any more chars then flush it to the console
			if ( s.length + a.length > CONSOLE_MAX_COLS )
			{
				this.output( s );
				s = '';
			}
			s += a;
		}
		// output the last chars in the buffer
		if ( s.length > 0 )
		{
			this.output( s );
		}
	}
	,
	inventory: function()
	{
		var s = '';
		var a;
		
		for ( var i = 0; i < core.inventory.length; i++ )
		{
			if ( core.inventory[i].number == HAS_ITEM )
			{
				a = core.inventory[i].name + ', ';
			}
			// when the buffer can't hold any more chars then flush it to the console
			if ( s.length + a.length > CONSOLE_MAX_COLS )
			{
				this.output( s );
				s = '';
			}
			s += a;
		}
		// output the last chars in the buffer
		if ( s.length > 0 )
		{
			this.output( s );
		}
	}
	,
	debug: function( input )
	{
		if ( input.length > 1 )
		{
			switch( input[1] )
			{
				case 'on': DEBUG = true; break;
				case 'hiobjs': 
					DEBUG_HIGHLIGHT_OBJS = !DEBUG_HIGHLIGHT_OBJS;
					for ( var i = 0; i < $o.length; i++ )
					{
						$o[i].img.style.border = (DEBUG_HIGHLIGHT_OBJS ? '1px solid red' : '' );
					}
					break;
					
				default: DEBUG = false;
			}
		}
		
		this.output( 'debug: ' + DEBUG );
		this.output( 'highlight objects: ' + DEBUG_HIGHLIGHT_OBJS );
	}
	,
	clear: function()
	{
		for ( var i = 0; i < CONSOLE_MAX_LINES; i++ )
		{
			this.lines[i] = '';
		}
		this.draw();
	}
	,
	help: function()
	{
		this.output( CMD_HELP + ': this stuff, duh!' );
		this.output( CMD_SHOW + ' &lt;variable>: shows the value of the variable &lt;variable>.' );
		this.output( CMD_SHOWVARS + ' [&lt;start> &lt;end>]: shows all variables from &lt;start> to &lt;end>.' );
		this.output( CMD_SHOWFLAGS + ' [&lt;start> &lt;end>]: shows all flags from &lt;start> to &lt;end>.' );
		this.output( CMD_SHOWOBJS + ' [&lt;start> &lt;end>]: shows all objects from &lt;start> to &lt;end>.' );
		this.output( CMD_INVENTORY + ' : shows all objects carried by ego.' );
		this.output( CMD_DEBUG + ' [on|hiobjs]: turns debug on|highlight objects.' );
		this.output( CMD_CLEAR + ': clears the console.' );
	}
	,
	output: function( str )
	{
		for ( var i = 0; i < CONSOLE_MAX_LINES-1; i++ )
		{
			this.lines[i] = this.lines[i+1];
		}
		this.lines[i] = str;
	}
};

function init_console()
{
	console.el = document.getElementById( 'console' );
}

var commands = new Object();
commands['new.room'] = ['n'];
commands['reposition'] = ['o','n','n'];
commands['get'] = ['s'];
commands['assignn'] = ['n','n'];

function parse_agi_command( input )
{
	var parent = input.indexOf( ' ' );
	if ( parent < 0 ) { parent = input.length }
	
	var name = input.substring( 0, parent );	
	var command = commands[name];
	var cmd;
	
	if ( command )
	{
		var args = input.substring( parent+1, input.length );
		args = args.split( /\s*,\s*/ );
		args = args.removeEmpty();
		
		if ( args.length != command.length ) { console.output( name + ": wrong parameters."); return true; }
		
		cmd = name.replace( '.', '_' ) + "(";
		for ( var i = 0; i < args.length; i++ )
		{
			switch ( command[i] )
			{
				case 'n': cmd += args[i] + ","; break;
				case 's': cmd += "'" + args[i] + "',"; break;
				case 'o': cmd += '$o[' + args[i].substring( 1, 5 ) + "],"; break;
			}
		}
		cmd = cmd.substring( 0, cmd.length-1 );
		cmd += ")";
		
		// poll command
		runCommand = cmd;
	}
	else
	{
		var res;
		var args = input.substring( parent+1, input.length );
		args = args.split( /\s+/ );
		args = args.removeEmpty();
	
		if ( res = name.match( /v(\d+)/ ) )
		{
			$v[res[1]] = parseInt( args[1] );
			cmd = name + ' = ' + args[1];
		}
	}
	
	console.output( cmd );
	
	return true;
}
