/* jQuery jqEasySuggest plugin
 * Examples and documentation at: http://www.jqeasy.com/
 * Version: 1.0 (24/11/2011)
 * No license. Use it however you want. Just keep this notice included.
 * Requires: jQuery v1.3+
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
 (function($) {
	$.fn.extend({
		jqEasySuggest: function(options){
			
			var settings = {
				ajax_file_path 		: "",
				min_keyword_length	: 2,
				showLoadingImage	: true,
				focus_color			: "",
				keyupDelay			: 200,
				id_element	 		: "",
				sql_match_type	 	: "starts",
				es_width			: "auto",
				es_opacity			: 0.95,
				es_max_results		: 10,
				es_offset_left		: 0,
				es_offset_top		: 0
			};
			
			return this.each(function(){
				var $this = $(this);
				var typingTimer;
				var tmp_id = Math.floor(Math.random()*100);
				
				// merge options with default settings
                if ( options ) { 
					$.extend( settings, options );
				}
				
				var offset = $this.offset();
				var current_border_width = $this.css("border-left-width");
				var current_border_style = $this.css("border-left-style");
				var current_border_color = $this.css("border-left-color");
				
				// set focus border style if defined
				if(settings.focus_color != ''){
					$this.focus(function() {
						$this.css("border",current_border_width + " " + current_border_style + " " + settings.focus_color);
					});
					$this.blur(function() {
						$this.css('border',current_border_width + " " + current_border_style + " " + current_border_color);
					});
				}
				
				$this.keydown(function(event) {
					var keyword = $this.val();
					switch(event.keyCode) {
						case 40: // down arrow
							if(!$("#easy_suggest_"+tmp_id).length && ($.trim(keyword).length >= settings.min_keyword_length)){
								getData(keyword);
							}
							found = false;
							$("#easy_list_"+tmp_id+" li").each(function(){
								if ($(this).hasClass('selected'))
									found = true;
							});
							if(found) {
								var sel = $("#easy_list_"+tmp_id+" li[class='selected']");
								// if this is last element then add selected class to first element
								if(sel.next().text() == "")					
									$("#easy_list_"+tmp_id+" li:first").addClass("selected");
								else
									sel.next().addClass("selected");
									sel.removeClass("selected");
							}
							else
								$("#easy_list_"+tmp_id+" li:first").addClass("selected");
							break;
						case 38: // up arrow
							found = false;
							$("#easy_list_"+tmp_id+" li").each(function(){
								if ($(this).hasClass('selected'))
									found = true;
							});
							if(found) {
								var sel = $("#easy_list_"+tmp_id+" li[class='selected']");
								// if this is first element then add selected class to last element
								if(sel.prev().text() == "")					
									$("#easy_list_"+tmp_id+" li:last").addClass("selected");
								else
									sel.prev().addClass("selected");
									sel.removeClass("selected");
							}
							else
								$("#easy_list_"+tmp_id+" li:last").addClass("selected");
							break;
						case 13: // enter key
							str = $("#easy_list_"+tmp_id+" li[class='selected']").text();
							if(str.length){
								$this.val(str);
								// store id of the selected option
								if(settings.id_element != "" && settings.id_element != null){
									$("#"+settings.id_element).val($("#easy_list_"+tmp_id+" li[class='selected'] a").attr("id"));
								}
							} else if(keyword == ''){
								if(settings.id_element != "" && settings.id_element != null){
									$("#"+settings.id_element).val('');
								}
							}
							$("#easy_suggest_"+tmp_id).fadeOut("fast", function() {
								$(this).remove();
							});
							//event.preventDefault();
							break;
						case 9: // tab key sets input values
							str = $("#easy_list_"+tmp_id+" li[class='selected']").text();
							if(str.length){
								$this.val(str);
								// store id of the selected option
								if(settings.id_element != "" && settings.id_element != null){
									$("#"+settings.id_element).val($("#easy_list_"+tmp_id+" li[class='selected'] a").attr("id"));
								}
								event.preventDefault();
								$this.focus();
							} else if(keyword == ''){
								if(settings.id_element != "" && settings.id_element != null){
									$("#"+settings.id_element).val('');
								}
							}
							$("#easy_suggest_"+tmp_id).fadeOut("fast", function() {
								$(this).remove();
							});
					}
				}).keyup(function(event){
					var keyword = $this.val();
					
					if($.trim(keyword).length >= settings.min_keyword_length){
						switch(event.keyCode) {
							case 40: case 38: case 9: // down arrow: up arrow: return/enter: tab:
								event.preventDefault();
								break;
							case 13:
							    break;
							case 27: // esc key hides the list
								$("#easy_suggest_"+tmp_id).fadeOut("fast", function() {
									$(this).remove();
								});
								break;
							default:
								// show the loading image
								if(settings.showLoadingImage){
									$this.css("background","url('/img/loading.gif') no-repeat scroll right center transparent");
								}
								// use a timer to introduce a slight delay when the user is typing
								// getData() doesn't fire until the user hasn't typed in a specified time (settings.keyupDelay) to reduce the number of ajax calls
								clearTimeout(typingTimer);
								typingTimer = setTimeout(function() { getData(keyword);	}, settings.keyupDelay)
						}
					} else {
						// keyword not min length 
						$("#easy_suggest_"+tmp_id).fadeOut("fast", function() {
							$(this).remove();
						});
					}
				});
				
				function getData(keyword) {
					$.ajax({
						type: "GET",
						url: settings.ajax_file_path,
						dataType: "json",
						data: { 
					        "data": keyword,
					        "source": settings.source,
					        "max_results": settings.es_max_results, 
					        "sql_match_type": settings.sql_match_type
					        
				        },
						success: function(data) {
							// ajax page should return 0 if no records found
							if(data != 0) {
								option_list = "<ul id='easy_list_"+tmp_id+"' class='easy_list'>";
								$.each(data, function(key, val) {
									// console.log(key + ' ' + val);
									if(settings.id_element != "" && settings.id_element != null){
										option_list += "<li><a href=\"#\" id=\""+key+"\">"+val+"</a></li>";
									} else {
										option_list += "<li><a href=\"#\">"+val+"</a></li>";
									}
								});
								option_list += "</ul>";
								
								if(!$("#easy_suggest_"+tmp_id).length){
									$("<div id='easy_suggest_"+tmp_id+"' class='easy_suggest'></div>").insertAfter($this)
//									.css("left",parseInt(offset.left) + parseInt(settings.es_offset_left))
//									.css("top",parseInt(offset.top) +  parseInt($this.outerHeight()) +  parseInt(settings.es_offset_top))
									.css("opacity",settings.es_opacity)
									.html(option_list).css("display","block");
									
									// set responce div width
									if(settings.es_width == "auto"){
										//var border_width = (parseInt($this.css("border-left-width")) + parseInt($this.css("border-right-width")) - 2);
										$("#easy_suggest_"+tmp_id).css("width",parseInt($this.outerWidth()) - 2);
									} else {
										$("#easy_suggest_"+tmp_id).css("width",parseInt(settings.es_width));
									}
								} else {
									$("#easy_suggest_"+tmp_id).html(option_list).css("display","block");
								}
							} else {
								$("#easy_suggest_"+tmp_id).fadeOut("fast", function() {
									$(this).remove();
								});
							}
							// remove the loading image
							if(settings.showLoadingImage){
								$this.css("background","");
							}
						},
						error: function(jqXHR, exception) {
							if (jqXHR.status === 0) {
								alert('Not connected.\n Verify Network.');
							} else if (jqXHR.status == 404) {
								alert('Requested page (' + settings.ajax_file_path + ') could not be found. [404]');
							} else if (jqXHR.status == 500) {
								alert('Internal Server Error [500]. ' + settings.ajax_file_path + ' has an error on the page.');
							} else if (exception === 'timeout') {
								alert('Time out error.');
							} else if (exception === 'parsererror') {
								alert('There was a parse error.\n\nPlease verify you have entered a value in \'ajax_file_path\' and verify your ajax response is in proper json format.');
							} else {
								alert('Uncaught Error.\n\n' + jqXHR.responseText);
							}
							// reomve the loading image
							if(settings.showLoadingImage){
								$this.css("background","");
							}
						}
					});
				}
										
				// style list li on mouseover
				$("#easy_list_"+tmp_id+" li").live("mouseover",function () {
					$("#easy_list_"+tmp_id+" li[class='selected']").removeClass("selected");
					$(this).addClass("selected");
				});
				
				// set input values on li click
				$("#easy_list_"+tmp_id+" li").live("click",function () {
					str = $("#easy_list_"+tmp_id+" li[class='selected']").text();
					$this.val(str);
					// store id of the selected option
					if(settings.id_element != "" && settings.id_element != null){
						$("#"+settings.id_element).val($("li[class='selected'] a").attr("id"));
					}
					$("#easy_suggest_"+tmp_id).fadeOut("fast", function() {
						$(this).remove();
					});
					return false;
				});
				
				// hide drop down on document click
				$(document).click(function(){
					if($("#easy_suggest_"+tmp_id).css("display") == "block"){
						$("#easy_suggest_"+tmp_id).fadeOut("fast", function() {
							$(this).remove();
						});
					}
				});
			});
		}
	});
})( jQuery );
