
(function($) {

	$.fn.terminal = function(url, options) {

		settings = $.extend({
			'max_height'		: '485',
			'form_method'		: 'post',
			'input_name'		: 'input',
			'post_vars'		: {},
			'custom_prompt'	: false,
	 		'focus_on_load'	: true,
			'submit_on_load'	: false,
			'grab_focus_on_click' : true,
			'hello_message'	: false,
			'unix_theme'		: true,
			'allow_empty_input' : true,
			'tab_width'		: 4,
			'disable_input'	: false,
			'onload'			: null,
			'nav_past_commands'	: true,
			'request_password'  : false,
			'display_prompt'	: true
		}, options);

		if (settings.custom_prompt)
		{
			settings.custom_prompt = $.trim(settings.custom_prompt) + ' ';
		}

		return this.each(function()
		{
			var terminal_container = $(this);
			var old_prompt = settings.custom_prompt;

			var history_list = [];
			var history_pos = -1;

			terminal_container.append('<div></div>');
			var terminal = terminal_container.find('div:last');

			if (settings.max_height == '100%')
			{
				settings.max_height = terminal_container.innerHeight();
			}

			terminal.css({
				'display'	: 'block',
				'overflow-x'	: 'hidden',
				'overflow-y'	: 'hidden',
				'padding'	: '0',
				'max-height': '400px' //settings.max_height + 'px'
			});

			terminal.append('<span></span');
			var terminal_output = terminal.find('span:last');

			terminal.append('<form method="'+settings.form_method+'" action="'+url+'"></form>');
			var terminal_form = $(this).find('form:last');

			if (settings.custom_prompt)
			{
				terminal_form.append('<span>' + settings.custom_prompt + '</span>');
			}

			terminal_form.css('display', 'inline');
			terminal_form.attr('onsubmit', 'return false;');

			var tabString = "";
			for (var i=0; i<settings.tab_width; i++)
			{
				tabString+= "&nbsp;";
			}

			var terminal_append = function(data)
			{
				var formattedData = $('<span/>').html(data.replace('\n', '<br/>'));
				var dataRows = formattedData.html().split(/\n/);
				data = '';
				for (row in dataRows)
				{
					data += '<span>' + dataRows[row].replace(/\t/g, tabString);
					if (!(row == dataRows.length-1 && (!dataRows[row] || !settings.custom_prompt)))
					{
						data+= '<br />';
					}
					data += '</span>';
				}

				terminal_output.append('<span>' + data + '</span>');

				if (settings.display_prompt)
				{
					terminal_form.show();
				}
				terminal_input.val('').focus();
				
				// if input is disabled, we trick a focus so the scrolling will be ok
				if (settings.disable_input)
				{
					terminal_input.removeAttr('disabled').focus().attr('disabled', 'disabled');
				}
				
				terminal.attr({ scrollTop: terminal.attr("scrollHeight")- terminal.height() });

			}
			// outsource this function for misc. implementations
			terminal_container[0].append = terminal_append;
			
			terminal_container[0].show_prompt = function () { terminal_form.show(); settings.display_prompt = true; }
			terminal_container[0].hide_prompt = function () { terminal_form.hide(); settings.display_prompt = false;}

			var terminal_clear = function()
			{
				terminal_output.text('');
				terminal.attr({ scrollTop: terminal.attr("scrollHeight")- terminal.height() });
				terminal_input.val('').focus();
			}
			terminal_container[0].clear = terminal_clear;
			
			var terminal_resize = function()
			{

				terminal_container.height($(window).height()+'px');
				//terminal.height($(window).height()+'px');
				terminal.height('485px');

				//terminal_container.css({'max-height': $(window).height() + 'px'});
				terminal_container.css({'max-height': '485px'});

                    terminal.css({'max-height': $(window).height() + 'px'});
                    settings.max_height = '400';

                    //settings.max_height = $(window).height();
                    terminal.attr({ scrollTop: terminal.attr("scrollHeight")- terminal.height() });
			}
			var terminal_command = function(e, first)
			{
				var first = first || false;
				var no_post = false;


				var val = $.trim(terminal_input.val());

				if ("" == val && !first)
				{
		 			if (!settings.allow_empty_input)
		 		 		return;
				}

	 			terminal_form.hide();
		 		if (("" != val || settings.allow_empty_input) && !settings.request_password)
				{
					var last_command = '<span>';
	 		 		last_command+= settings.custom_prompt? settings.custom_prompt : '';
		 	 		last_command+= htmlentities(val) + '<br />';
		 			terminal_output.append(last_command);
		 			if (val == '')
		 			{   
						no_post = true;
		 			}
	 			}

				if (val != '' && !settings.request_password)
				{
                    	history_list.push(val);
                    	history_pos = -1;
    				}
    				

	 			post_vars = settings.post_vars;
	 			post_vars[settings.input_name] = encodeURIComponent(val);


				 if (settings.request_password)
				 {
					 settings.request_password = false;
					 terminal_input.val('').css({'color':'#FFFFFF'});
					 terminal_form.find('span:last').html(old_prompt);
					 settings.custom_prompt = old_prompt;
					 
					 post_vars['auth'] = 1;
				 } else {
				 	 post_vars['auth'] = 0;
				 }





				function terminal_command_success(data)
				{
					var output = '';

					switch (data.response_type)
					{
						case 'css':
							var styleTag = document.createElement('link');
							styleTag.setAttribute('type', 'text/css');
							styleTag.setAttribute('rel', 'stylesheet');
							styleTag.setAttribute('href', data.response);
                                   document.getElementsByTagName('head')[0].appendChild(styleTag);
							output = 'color scheme changed.';
						break;

 						case 'link':
 							output = '<a href="'+data.response+'" target="_blank">'+data.response+'</a><br />';
						break;

						case 'img':
 							load_image(data.response);
 							output = '';
 							return true;
						break;
						
						case 'mp3':
							var mp3_file = data.response;
							output = '<script>soundManager.createSound(\'myNewSound\', \''+mp3_file+'\');soundManager.play(\'myNewSound\');soundManager.setVolume(\'myNewSound\',50);</script>';
						break;

						case 'stop_mp3':
							output = '<script>soundManager.stopAll();</script>' + data.response;
                                   //output = '<script>soundManager.stop(\'myNewSound\')</script>' + data.response;
							//output = '';
						break;

						case 'yt':
							var tmp_yt = data.response;
						     output = '<object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/'+tmp_yt+'&autoplay=1&hl=en_US&fs=1&rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/'+tmp_yt+'&autoplay=1&hl=en_US&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object>';
						break;

						case 'swf':
							var swf_src = data.response;
							var tmp_swf_name = 'swf_'+(1 + Math.floor(Math.random() * 1000));
							output = '<div id="'+tmp_swf_name+'"></div><script type="text/javascript">swfobject.embedSWF("'+swf_src+'", "'+tmp_swf_name+'", "300", "120", "9.0.0");</script>';
						break;

						case 'redirect':
							output = 'loading...';
							window.location.href = data.response;
						break;
						
						case 'auth':
						     terminal_input.val('').css({'color':'#FFFFFF'});
						     terminal_form.find('span:last').html(old_prompt);

                                   if (data.response == 'valid')
                                   {
                                        settings.custom_prompt = "<font color='lime'>root@bt4 </font><font color='white'>#</font> ";
                                        terminal_form.find('span:last').html("<font color='lime'>root@bt4 </font><font color='white'>#</font> ");
							} else {
								output = 'Password:<br />su: incorrect password';
                                        settings.custom_prompt = old_prompt;
							}

						break;
						case 'logout':
						     terminal_input.val('').css({'color':'#FFFFFF'});
							terminal_form.find('span:last').html(old_prompt);
                                   settings.custom_prompt = old_prompt;
						break;

						case 'su':

                                   settings.request_password = true;
                                   /* setup input to send password */
                                   terminal_form.find('span:last').text('Password: ');  
							terminal_input.val('').css({'color':'#000000'});

                                   output = '';
                                   //return true;
						break;

						case 'text':
						default:
 							output = data.response;
						break;
					}
					return terminal_append(output);
				}

				function terminal_command_error(x, tStatus)
				{
					var out = 'ERROR: ';
					switch(tStatus)
					{
						case 'timeout':
							out+= 'Server timeout. Try again later.';
							break;
						case 'notmodified':
							out+= 'Server did not response properly. Try again.';
							break;
						case 'parsererror':
							out+= 'Client error. Try again.';
							break;
						default:
						case 'error':
							out+= 'A server error has occured. Check your command.';
							break;
					}
					return terminal_command_success(out);
				}

				function load_image(img_src)
				{
					var image = new Image();
					image.onerror = function()
					{
						terminal_append('unable to load image.');	
					};
					image.onload = function() 
					{
						var img_h = image.height;
						var tmp_img_id = 'img_'+(1 + Math.floor(Math.random() * 1000));
						var output = '<div style="height:'+img_h+'px;"><img src="'+img_src+'" id="'+tmp_img_id+'" style="height:'+img_h+'px;display:none;" /></div>';
						terminal_append(output);
						$("#"+tmp_img_id).fadeIn(1000,function()
						{
							terminal.attr({ scrollTop: terminal.attr("scrollHeight")- terminal.height() });
						});
					};
					image.src = img_src;

				}

				if (!no_post)
				{
				$.ajax({
					'type' : terminal_form.attr('method'),
					'url' : terminal_form.attr('action'),
					'cache' : false,
					'data' : post_vars,
					'dataType' : 'json',
					'success' : terminal_command_success,
					'error' : terminal_command_error,
				});
				} else {
				    terminal_append('');	
				}
				if (typeof e == 'object' && typeof e['preventDefault'] == 'function')
				{
					e.preventDefault();
				}

			}
			terminal_form.submit(terminal_command);

			terminal_form.append('<input type="text" name="'+settings.input_name+'" />');
			var terminal_input = terminal_form.find('input:last');
			//terminal_input.css('width', '75%');
			terminal_input.attr('autocomplete', 'off');

			if (settings.unix_theme)
			{
				terminal_container.css({
					'border' : 'none'
				});
				terminal_form.css({
					'padding' : '0',
					'margin' : '0'
				});
				terminal_input.css({
					'padding' : '0',
					'margin' : '0'
				});
			}

			$(document).ready(function()
			{
				if (settings.grab_focus_on_click)
				{
					terminal_container.mouseup(function()
					{
						try{
						if ("" == window.getSelection())
						{
							$(terminal_input.focus());
						}
						} catch (e){}
					});
				}
				
				if (settings.nav_past_commands)
				{
					terminal_container.keyup(function(e)
					{
						var key = 0;
					     if (e == null)
						{
					     	key = event.keyCode;
					     } else
						{
					     	key = e.which;
					     }

						switch(key)
						{
							case 38:
			
							  if (history_pos <= 0)
							  {
							  	if (history_pos < 0)
							  	{
							  	history_pos  = history_list.length - 1;
							  	} else {
								history_pos  = 0;
							     }
							  } else {
							  	history_pos  = history_pos -1;
				 			  }
			                      $(terminal_input.val(history_list[history_pos]).focus());
							  break;
			
							case 40:
							  if (history_pos >= history_list.length-1)
							  {
							  	if (history_pos == history_list.length-1)
							  	{
							  		history_pos  = history_list.length;
							  		$(terminal_input.val('').focus());
							  	}
							  } else {
							  	history_pos  = history_pos + 1
							  	$(terminal_input.val(history_list[history_pos]).focus());
				 			  }
							  break;
						}


					});
				}

				if (settings.hello_message)
					terminal_output.append('<span>' + settings.hello_message + '<br /></span>');

				if (settings.submit_on_load)
					terminal_command(null, true);

				if (settings.focus_on_load)
					terminal_input.val('').focus();

				if (settings.disable_input)
					terminal_input.attr('disabled', 'disabled');

				if (settings.onload)
					settings.onload();
					
				$(window).resize(terminal_resize);
				terminal_resize();
				//$(window).onclick(function()
				//{
				//	terminal_input.focus();
				//});

			});
		});

	}

}(jQuery));

function play_mp3(mp3_file)
{
	soundManager.createSound('bgSound', mp3_file);
	soundManager.play('bgSound');
	soundManager.setVolume('bgSound',70);
}
function write_delay(output,delay)
{
	setTimeout(function (){ $('#terminal_container')[0].append(output); },delay);
}
function clear_delay(delay)
{
	setTimeout(function (){ $('#terminal_container')[0].clear(); },delay);
}
function terminal_fade_out()
{
	$('#terminal_container').fadeOut(1500);
}
function terminal_fade_in()
{
	$('#terminal_container').fadeIn(1500);
}

function htmlentities (string, quote_style) {
    // Convert all applicable characters to HTML entities  
    // 
    // version: 1003.2411
    // discuss at: http://phpjs.org/functions/htmlentities    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: nobbler
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Ratheous
    // -    depends on: get_html_translation_table
    // *     example 1: htmlentities('Kevin & van Zonneveld');    // *     returns 1: 'Kevin &amp; van Zonneveld'
    // *     example 2: htmlentities("foo'bar","ENT_QUOTES");
    // *     returns 2: 'foo&#039;bar'
    var hash_map = {}, symbol = '', tmp_str = '', entity = '';
    tmp_str = string.toString();    
    if (false === (hash_map = this.get_html_translation_table('HTML_ENTITIES', quote_style))) {
        return false;
    }
    hash_map["'"] = '&#039;';    for (symbol in hash_map) {
        entity = hash_map[symbol];
        tmp_str = tmp_str.split(symbol).join(entity);
    }
        return tmp_str;
}

function get_html_translation_table (table, quote_style) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philip Peterson
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: noname
    // +   bugfixed by: Alex
    // +   bugfixed by: Marco
    // +   bugfixed by: madipta
    // +   improved by: KELAN
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Frank Forte
    // +   bugfixed by: T.Wild
    // +      input by: Ratheous
    // %          note: It has been decided that we're not going to add global
    // %          note: dependencies to php.js, meaning the constants are not
    // %          note: real constants, but strings instead. Integers are also supported if someone
    // %          note: chooses to create the constants themselves.
    // *     example 1: get_html_translation_table('HTML_SPECIALCHARS');
    // *     returns 1: {'"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;'}
    
    var entities = {}, hash_map = {}, decimal = 0, symbol = '';
    var constMappingTable = {}, constMappingQuoteStyle = {};
    var useTable = {}, useQuoteStyle = {};
    
    // Translate arguments
    constMappingTable[0]      = 'HTML_SPECIALCHARS';
    constMappingTable[1]      = 'HTML_ENTITIES';
    constMappingQuoteStyle[0] = 'ENT_NOQUOTES';
    constMappingQuoteStyle[2] = 'ENT_COMPAT';
    constMappingQuoteStyle[3] = 'ENT_QUOTES';

    useTable       = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
    useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT';

    if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
        throw new Error("Table: "+useTable+' not supported');
        // return false;
    }

    entities['38'] = '&amp;';
    if (useTable === 'HTML_ENTITIES') {
        entities['160'] = '&nbsp;';
        entities['161'] = '&iexcl;';
        entities['162'] = '&cent;';
        entities['163'] = '&pound;';
        entities['164'] = '&curren;';
        entities['165'] = '&yen;';
        entities['166'] = '&brvbar;';
        entities['167'] = '&sect;';
        entities['168'] = '&uml;';
        entities['169'] = '&copy;';
        entities['170'] = '&ordf;';
        entities['171'] = '&laquo;';
        entities['172'] = '&not;';
        entities['173'] = '&shy;';
        entities['174'] = '&reg;';
        entities['175'] = '&macr;';
        entities['176'] = '&deg;';
        entities['177'] = '&plusmn;';
        entities['178'] = '&sup2;';
        entities['179'] = '&sup3;';
        entities['180'] = '&acute;';
        entities['181'] = '&micro;';
        entities['182'] = '&para;';
        entities['183'] = '&middot;';
        entities['184'] = '&cedil;';
        entities['185'] = '&sup1;';
        entities['186'] = '&ordm;';
        entities['187'] = '&raquo;';
        entities['188'] = '&frac14;';
        entities['189'] = '&frac12;';
        entities['190'] = '&frac34;';
        entities['191'] = '&iquest;';
        entities['192'] = '&Agrave;';
        entities['193'] = '&Aacute;';
        entities['194'] = '&Acirc;';
        entities['195'] = '&Atilde;';
        entities['196'] = '&Auml;';
        entities['197'] = '&Aring;';
        entities['198'] = '&AElig;';
        entities['199'] = '&Ccedil;';
        entities['200'] = '&Egrave;';
        entities['201'] = '&Eacute;';
        entities['202'] = '&Ecirc;';
        entities['203'] = '&Euml;';
        entities['204'] = '&Igrave;';
        entities['205'] = '&Iacute;';
        entities['206'] = '&Icirc;';
        entities['207'] = '&Iuml;';
        entities['208'] = '&ETH;';
        entities['209'] = '&Ntilde;';
        entities['210'] = '&Ograve;';
        entities['211'] = '&Oacute;';
        entities['212'] = '&Ocirc;';
        entities['213'] = '&Otilde;';
        entities['214'] = '&Ouml;';
        entities['215'] = '&times;';
        entities['216'] = '&Oslash;';
        entities['217'] = '&Ugrave;';
        entities['218'] = '&Uacute;';
        entities['219'] = '&Ucirc;';
        entities['220'] = '&Uuml;';
        entities['221'] = '&Yacute;';
        entities['222'] = '&THORN;';
        entities['223'] = '&szlig;';
        entities['224'] = '&agrave;';
        entities['225'] = '&aacute;';
        entities['226'] = '&acirc;';
        entities['227'] = '&atilde;';
        entities['228'] = '&auml;';
        entities['229'] = '&aring;';
        entities['230'] = '&aelig;';
        entities['231'] = '&ccedil;';
        entities['232'] = '&egrave;';
        entities['233'] = '&eacute;';
        entities['234'] = '&ecirc;';
        entities['235'] = '&euml;';
        entities['236'] = '&igrave;';
        entities['237'] = '&iacute;';
        entities['238'] = '&icirc;';
        entities['239'] = '&iuml;';
        entities['240'] = '&eth;';
        entities['241'] = '&ntilde;';
        entities['242'] = '&ograve;';
        entities['243'] = '&oacute;';
        entities['244'] = '&ocirc;';
        entities['245'] = '&otilde;';
        entities['246'] = '&ouml;';
        entities['247'] = '&divide;';
        entities['248'] = '&oslash;';
        entities['249'] = '&ugrave;';
        entities['250'] = '&uacute;';
        entities['251'] = '&ucirc;';
        entities['252'] = '&uuml;';
        entities['253'] = '&yacute;';
        entities['254'] = '&thorn;';
        entities['255'] = '&yuml;';
    }

    if (useQuoteStyle !== 'ENT_NOQUOTES') {
        entities['34'] = '&quot;';
    }
    if (useQuoteStyle === 'ENT_QUOTES') {
        entities['39'] = '&#39;';
    }
    entities['60'] = '&lt;';
    entities['62'] = '&gt;';


    // ascii decimals to real symbols
    for (decimal in entities) {
        symbol = String.fromCharCode(decimal);
        hash_map[symbol] = entities[decimal];
    }
    
    return hash_map;
}


/*
 * AJAX Terminal (0.4.1)
 * by Sagie Maoz (n0nick.net)
 * n0nick@php.net
 * Copyright (c) 2009 Sagie Maoz <n0nick@php.net>
 * Licensed under the GPL license, see http://www.gnu.org/licenses/gpl-3.0.html 
 *
 *
 * MODIFIED: 20100411 - added additional features, this is a customized version - wildwestcode.com
 */
