jQuery(function($){
    $.fn.autocomplete = function(settings) {
		
		var element = this;
		var element_id = element.attr("id");
		var height = element.outerHeight();
		var width = element.innerWidth();
		var position = element.offset();
		var active = -1;
		var timeout = null;
		
		element.attr("autocomplete", "off");
		
		/************* Settings *************/
		var settings = $.extend({
			url: element.parents("form").attr("action")+"ajax",
			minchar: 2,
			delay: 400,
			action: "submit",
			loader: false,
			loaderwidth: 16,
			displayeddata: "",
			predecorator: new Array(),
			postdecorator: new Array(),
			redirecturl: "",
			redirectparam: ""
		},settings);
		
		/************* KEY *************/
		element.keyup(function(key) {
			switch(key.keyCode) {				
				case 38: //up
					move(-1);
					break;
				case 40: //down
					if( ! $("div.autocomplete-result").size())
					{
						send();
					} else {
						move(1);
					}
					break;
				case 27: // escape
					destroy();
					break;
				default:
					if (timeout) clearTimeout(timeout);
					timeout = setTimeout(function(){send();}, settings.delay);										
					break;
			}			
		});
		
		element.keydown(function(key) {
			switch(key.keyCode) {
				case 13: //Enter
					element.blur();
					if($("div.autocomplete-result ul li.active").size() > 0)
					{
						selectitem();
					} else {
						element.parents("form").submit();
					}
					key.preventDefault();
					break;
			}
		});
		
		/************* send *************/
		function send()
		{
			if(element.focus)
			{
				element_value = element.val();
				if(element_value.length >= settings.minchar && element_value.length > 0)
				{	
					if(settings.loader && settings.loader != "")
					{
						var backleft = width - settings.loaderwidth - 10;
						element.css("background", "url("+settings.loader+") no-repeat "+backleft+"px center");
					}
					
					$.getJSON(settings.url, { value: element_value }, function(json) {
						makelist(json);
						if(settings.action == "complete") {
							stockdata(json);	
						}
						element.css("background", "none");
					});					
				}
				
			}
		}
		
		/************* makelist *************/
		function makelist(data)
		{
			var output = "";
			
			if(data.length > 0)
			{
				for (var i = 0; i < data.length; i++) 
				{
					var content = "";
					
					if(settings.displayeddata != "")
					{
						for(var j = 0; j < settings.displayeddata.length; j++)
						{
							var keydata = settings.displayeddata[j];						
							content += decoration(keydata, data[i][keydata], j);						
						}
					} else {
						var index = 0;
						for(var j in data[i]) 
						{						
							content += decoration(j, data[i][j], index);
							index ++;
						}
					}
					
					var rel= "";					
					if(settings.action == "redirect") {
						rel = " rel='"+data[i][settings.redirectparam]+"'";
					}
					
					output +=  "<li id='"+i+"item-result'"+rel+">"+content+"</li>";	
				}		
				insert_output(output);
			} else {
				element.css("background", "none");
			}
		}
		
		/************* makelist *************/
		function stockdata(data)
		{
			var output = "";
			var content_output = "";
			
			if(data.length > 0)
			{
				for (var i = 0; i < data.length; i++) 
				{
					var content = "";
					for(var j in data[i]) 
					{
						content += "<div class='"+j+"'>"+data[i][j]+"</div>";
					}
					content = "<div class='"+i+"item'>"+content+"</div>";
					content_output += content;					
				}
				
				output += "<div id='autocomplete_stock' style='display: none;'>"+content_output+"</div>";				
				$('body').append(output);
			}
		}
		
		/************* decoration *************/
		function decoration(keydata, text, index)
		{
			var spredecorator = " ";
			var spostdecorator = "";
			
			if(index == 0) {
				spredecorator = "";	
			}
			
			if(settings.predecorator[keydata])
			{
				spredecorator = settings.predecorator[keydata];
			}		
		
			if(settings.postdecorator[keydata])
			{
				spostdecorator = settings.postdecorator[keydata];
			}
			
			return spredecorator+text+spostdecorator;
		}
		
		/************* insert_output *************/
		function insert_output(output)
		{
			if( ! $("div.autocomplete-result").size())
			{
				var top = position.top + height;
				var left = position.left;

				output = "<div class='autocomplete-result' style='position:absolute; top:"+top+"px; left:"+left+"px;'><ul>"+output+"</ul></div>";
				$('body').append(output);
			} else {
				$("div.autocomplete-result ul").html(output);
			}	
			
			$("div.autocomplete-result ul li").mouseover(function() {
				$("div.autocomplete-result ul li").removeClass("active");
				$(this).addClass('active');	
			});
			
			$("div.autocomplete-result ul li").click(function() {
				$("div.autocomplete-result ul li").removeClass("active");
				$(this).addClass('active');
				selectitem();		
			});		
			
			var destroyautocomplete = 0;
			
			element.mouseleave(function() {
				destroyautocomplete = 1;				
			}).mouseenter(function() {
				destroyautocomplete = 0;
			});
			
			$("div.autocomplete-result").mouseleave(function() {
				destroyautocomplete = 1;
			}).mouseenter(function() {
				destroyautocomplete = 0;
			});
			
			$("html").click(function() {
				if(destroyautocomplete == 1)
				{
					destroy();
				}
			});
			$("html").keyup(function(key) {
				switch(key.keyCode) {				
					case 27: // escape
						destroy();
						break;
				}			
			});
			
		}
		
		/************* move *************/
		function move(step)
		{
			var lis = $("div.autocomplete-result ul li");
			if (!lis) return;
			
			$("div.autocomplete-result ul li").each(function() {
				if($(this).hasClass('active'))
				{
					active = $("div.autocomplete-result ul li").index(this);
				}
			});
	
			active += step;
	
			if (active < 0) {
				active = 0;
			} else if (active >= lis.size()) {
				active = lis.size() - 1;
			}
	
			lis.removeClass("active");
	
			$(lis[active]).addClass("active");			
		}
		
		/************* selectitem *************/
		function selectitem()
		{
			var value =  $("div.autocomplete-result ul li.active").attr('id');
			var content = $("div.autocomplete-result ul li.active").text();
			element.val(content);
			if(settings.action == "submit")
			{
				element.parents("form").submit();
			}
			if(settings.action == "complete")
			{
				var selectid = parseInt(value);
				completeform(selectid);
			}
			if(settings.action == "redirect") {
				var redirectparamvalue = $("div.autocomplete-result ul li.active").attr('rel');
				window.location.href = settings.redirecturl+settings.redirectparam+"/"+redirectparamvalue;
			}
			destroy();
		}
		
		/************* selectitem *************/
		function completeform(selectid)
		{
			var selectedclass = "";
			var valeur = "";
			$("#autocomplete_stock div."+selectid+"item div").each(function() {
				selectedclass = $(this).attr("class");
				valeur = $(this).text();
				element.parents("form").find("#"+selectedclass).val(valeur);
				$("#autocomplete_stock").remove();
			});
		}
			
		/************* destroy *************/
		function destroy()
		{
			if (timeout) clearTimeout(timeout);
			$('.autocomplete-result').remove();
			active = -1;
		}						 
		
	}
})