/**
*    Json key/value autocomplete for jQuery 
*    Provides a transparent way to have key/value autocomplete
*    Copyright (C) 2008 Ziadin Givan www.CodeAssembly.com  
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Lesser General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU Lesser General Public License
*    along with this program.  If not, see http://www.gnu.org/licenses/
*    
*    Examples 
*     $("input#example").autocomplete("autocomplete.php");//using default parameters
*     $("input#example").autocomplete("autocomplete.php",{minChars:3,timeout:3000,validSelection:false,parameters:{'myparam':'myvalue'},before : function(input,text) {},after : function(input,text) {}});
*    minChars = Minimum characters the input must have for the ajax request to be made
*     timeOut = Number of miliseconds passed after user entered text to make the ajax request   
*    validSelection = If set to true then will invalidate (set to empty) the value field if the text is not selected (or modified) from the list of items.
*    parameters = Custom parameters to be passed
*    after, before = a function that will be caled before/after the ajax request
*/

function urlencode(text)
{
	var trans = [];
	for (var i = 0x410; i <= 0x44F; i++) trans[i] = i - 0x350;
	trans[0x401] = 0xA8;
	trans[0x451] = 0xB8;
	var ret = [];
	for (var i=0; i<text.length; i++)
	{
		var n = text.charCodeAt(i);
		if(typeof trans[n] != 'undefined') n = trans[n];
		if(n <= 0xFF) ret.push(n);
	}
	return escape(String.fromCharCode.apply(null,ret));
}

jQuery.fn.autocomplete = function(url, search_form_id, settings ) 
{
	return this.each( function()//do it for each matched element
	{
		//this is the original input
		var textInput = $(this);
		textInput.after('<ul class="autocomplete"></ul>');
		var list = textInput.next();
		var oldText = '';
		var typingTimeout;
		var size = 0;
		var selected = -1;

		settings = jQuery.extend(//provide default settings
		{
			minChars : 3,
			timeout: 1000,
			after : null,
			before : null,
			validSelection : true,
			parameters : {'inputId' : textInput.attr('id')}
		} , settings);

		function getData(text)
		{
			window.clearInterval(typingTimeout);
			if (text != oldText && (settings.minChars != null && text.length >= settings.minChars))
			{
				clear();
				if (settings.before == "function") 
				{
					settings.before(textInput,text);
				}
				textInput.addClass('autocomplete-loading');
				settings.parameters.text = urlencode(text);
				$.getJSON(url,settings.parameters,function(data)
//				var a = function(data) // for debug
				{
					list.css({top: textInput.offset().top + textInput.outerHeight(), left: textInput.offset().left, width: textInput.width()})
					var items = '';
					if (!!data)
					{
						size = data.length;
						for (i = 0; i < data.length; i++)//iterate over all options
						{
							for ( key in data[i] )//get key => value
							{    
								items += '<li value="' + key + '" class="suggest_list">'
									+ data[i][key].replace(
										new RegExp("(" + text + ")","i")
										,"<strong>$1</strong>"
									) + '</li>';
							}
						}
                        
						if (items != '') {
							list.html(items).show();
							list.children().hover(function() { 
									$(this).addClass("selected").siblings().removeClass("selected");
								}, 
								function() { $(this).removeClass("selected") } 
							);
							list.children().mousedown(function() {
								textInput.val($(this).text());
								clear();
								textInput.get(0).form.submit();
							});
						}
                                               
						if (settings.after == "function") {
							settings.after(textInput,text);
						}
                        
					}
					textInput.removeClass('autocomplete-loading');
//				}([{1: 'Line 1'}, {2: 'Line 2'}]); // for debug
				});
				oldText = text;
			}
		}
        
		function clear()
		{
			list.hide();
			size = 0;
			selected = -1;
		}

		$(window).resize(function(e)
		{
			list.css({top: textInput.offset().top + textInput.outerHeight(), left: textInput.offset().left, width: textInput.outerWidth()});
		});

		textInput.blur(function(e) 
		{
			clear();
		});
        
		textInput.keydown(function(e) {
			window.clearInterval(typingTimeout);
			if(e.which == 27) {//escape
				clear();
			} else if (e.which == 46 || e.which == 8) {//delete and backspace
				clear();
				getData(textInput.val());
			} else if(e.which == 13) { //enter 
				if (selected > -1) { //if the list is not visible then make a new request, otherwise hide the list
					clear();
					inputText.get(0).form.submit();
				}
				e.preventDefault();
				return false;
			} else if(e.which == 40 || e.which == 9 || e.which == 38) { //move up, down 
				if (list.css("display") == "none") {
					getData(textInput.val());
				} else {
					switch(e.which) {
						case 40: 
						case 9:
							selected = (selected < size - 1 && selected != -1) ? selected + 1 : 0;
							break;
						case 38:
							selected = (selected <= 0) ? size - 1 : selected - 1;
					}
					//set selected item and input values
					textInput.val(list.children().removeClass('selected').eq(selected).addClass('selected').text());
				}
			} else { 
				typingTimeout = window.setTimeout(function() {
						getData(textInput.val()) 
					},
					settings.timeout
				);
			}
		});
	});
};


