/*! jQuery Suggest Search Plugin.
 * 
 *  @author Timo Massari  
 */
(function($) {
	 
	$.fn.suggestSearch = function(settings) {
	  
		var config = {
				'suggestURL' : 'http://some.suggest.url',
				'searchArea' : 'searcharea',
				'suggestSearchButton' : 'suggestSearchButton',
				'itemsFound' : 'Items found: ',
				'additionalItems' : 'Additional items: ',
				'goImage' : './images/but_go.gif',
				'workingImage' : './images/but_go.gif',
				'workingImageOnly' : false,
				'numericInputOnly' : false,
				'autoSubmit' : true,
				'clearInputField' : false,
				'minLength' : 3 
		};	
		 
		if (settings) $.extend(config, settings);
		
		var $suggestSearchInputField = jQuery(this);
		var $suggestSearchButton = jQuery("#"+config.suggestSearchButton);
		var $searchForm = jQuery('#'+config.searchFormId);
		
		var numberOfSearchResults = 0;
		var inputFieldCleared = false;
		var cache = {};
		
		var updateSuggestSearchInputField = function(value, label) {
			
			(value && value != " ") ? $suggestSearchInputField.val(value) : $suggestSearchInputField.val(label);
		};
		
		
		var hideWorkingImage = function() {

			(config.workingImageOnly) ? $suggestSearchButton.hide() : $suggestSearchButton.attr("src", config.goImage);
		}
		
		var showWorkingImage = function() {

			(config.workingImageOnly) ? $suggestSearchButton.show() : $suggestSearchButton.attr("src", config.workingImage);
		}

		var populateResponse = function(response, result) {
			
			response(
					
				jQuery(result).map(function(index, element) {
						
					return {
					   	value : element.articleNo,
					   	label : element.articleDescription
					};
				})
			);
		};
		
		var renderResult = function(response, result) {
			
			hideWorkingImage();
		
			numberOfSearchResults =  parseInt(result.numberOfSearchResults);						
			populateResponse(response, result.result);
		}
		
		var requestSuggestSearchData = function(request, response) {
			
			var term = request.term.toLowerCase();
			
			var cachedResult = cache[term];
			
			if (cachedResult) {
			
				renderResult(response, cachedResult);
			}
			else {
			
				jQuery.ajax({
	
					url: config.suggestURL,
					dataType: "jsonp",
					data: {
						searchTerm: term
					},
					success: function(result) {
						
						cache[term] = result;						

						renderResult(response, result);
					},
					error: function(XMLHttpRequest, textStatus, errorThrown) {
					
						console.log("error while getting suggestSearch data: "+errorThrown);
					}
				});
			}
		};
		
		var $autocomplete = $suggestSearchInputField.autocomplete({
			
			minLength: config.minLength,
			
			appendTo: "#"+config.searchArea,

			search: function(event, ui) {
				
				showWorkingImage();
			},
			
			close: function(event, ui) {
				
				hideWorkingImage();
			},
			
			source: function(request, response) {
				
				requestSuggestSearchData(request, response);
			},
			
			focus: function(event, ui) {
				
				return false;
			},
			
			select: function(event, ui) {
				
				updateSuggestSearchInputField(ui.item.value, ui.item.label);
				
				if (config.autoSubmit) {
					
					$searchForm.submit();
				}
			}
		});
		
		$autocomplete.data( "autocomplete" )._renderMenu = function( ul, items ) {
			
			if (!items[0]) return;
			
			var that = this;
			
			jQuery( '<li class="ui-autocomplete-text"></li>' ).append(config.itemsFound + numberOfSearchResults).appendTo( ul );
						
			jQuery.each( items, function( index, item ) {
				
				that._renderItem( ul, item );
			});
			
			if (items.length < numberOfSearchResults) {
				
				jQuery( '<li class="ui-autocomplete-text"></li>' ).append(config.additionalItems).appendTo( ul );
			}
		};
			
		$autocomplete.data( "autocomplete" )._renderItem = function( ul, item ) {

			// RegExp from http://jqueryui.com/demos/autocomplete/#combobox
			var regExp = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" 
					+ jQuery.ui.autocomplete.escapeRegex(this.term) 
					+ ")(?![^<>]*>)(?![^&;]+;)", "gi");
			
			var value = ""; 
			if (item.value) {
				
				var value = item.value.replace(regExp, "<strong class='strongRed'>$1</strong>");
			}
			
			var label = "";
			if (item.label) {
				
				label = item.label.replace(regExp, "<strong class='strongRed'>$1</strong>");
			}
			
			return jQuery( '<li class="ui-autocomplete-item"></li>' )
						.data( "item.autocomplete", item )
						.append( "<a>" + label + "<span class='value'>" + value + "</span></a>" )
						.appendTo( ul );
		};
		
		if (config.clearInputField) {
			
			$suggestSearchInputField.focus(function(even) {
				
				if (!inputFieldCleared) {
				
					$suggestSearchInputField.val("");
					inputFieldCleared = true;
				}
			});
		}
		
		if (config.autoSubmit) {

			$suggestSearchInputField.keypress(function(event) {
				
				if (event.keyCode == '13') {
	
					$searchForm.submit();
				}
			});
		}
		
		if (config.numericInputOnly) {
			
			$suggestSearchInputField.keypress(function(event) {
				
				var keyCode = event.which;
				
				if (keyCode == 0 || keyCode == 8 || keyCode == 13 || keyCode == 32 || keyCode == 97 || keyCode == 99 || keyCode == 118 || keyCode == 120) {
					
					return true;
				}
				
				if (keyCode < 48 || keyCode > 57) {
					
					return false;
				}
			});
		};
		
	};
	
})(jQuery);
