/**
 * Autocomplete class for JQuery.
 * This is a somewhat modified version of Dylan Verheul's jQuery Autcomplete plug-in
 * adding a distinct Solr twinge and customising how it worked to suit our needs.
 */
jQuery.autocomplete = function(input, options) 
{
	var $input = $(input).attr("autocomplete", "off");
	var results  = document.createElement("div");
	var $results = $(results);
	
	$results.hide().addClass(options.resultsClass).css("position", "absolute");	
	$results.remove();
	$("body").append(results);

	var active = -1;
	
	// Needed the enter key on a keypress event otherwise the preventDefault did not work
	$input.keypress(function(e) 
	{
		if (e.keyCode == 13)
		{
			if(selectCurrent())
			{
				e.preventDefault();

				hideResultsNow();
				$("#prodfind").submit();
			}
		}
	});

	$input.keyup(function(e) 
	{
		lastKeyPressCode = e.keyCode;

		switch(e.keyCode)
		{
			case 38: 
				// up
				moveSelect(-1);
			break;
			case 40: 
				// down
				moveSelect(1);
			break;
			default:
				
				if (lastKeyPressCode == 8 && $input.val().length == 0)
				{
					hideResults();
				}
			
				setTimeout(querySolr, 100);
			break;
		}		
	})
	.blur(function() 
	{
		hideResults();
	});
	
	function querySolr()
	{
		searchtext = $input.val();
		searchtext = searchtext.replace(/\s+/g, "");

		if (searchtext.length > 0)
		{
			var url = options.url+"?q="+searchtext+'&callback=?';	
	
			$.getJSON(url, function(json)
			{
				terms = [];
					
				jQuery.each(json.response.docs, function() 
				{	   
					text       = '';
				  	searchterm = '';
				  	 	 
				  	jQuery.each(this, function (key, val)
				  	{	    	  
					    	  if (key == 'searchterm')
					    	  {
					    		  searchterm = val;		  
					    	  }
					    	  
					    	  if (key == 'popularity')
					    	  {
					    		  popularity = val;		
					    	  }
					      });	      

					     terms.push(searchterm);							    
					});	

					processData(terms);
				}
			);
		}
	}	

	function processData(data) 
	{
		if (data) 
		{
			results.innerHTML = "";

			if(data.length == 0) 
			{
				return hideResults();
			}

			results.appendChild(buildDom(data));
			showResults();
		} 
		else 
		{
			hideResults();
		}
	};
	
 	function moveSelect(step)
 	{
		var lis = $("li", results);
		if (!lis) return;

		active += step;

		if (active < 0) 
		{
			active = 0;
		} 
		else if (active >= lis.size()) 
		{
			active = lis.size() - 1;
		}

		lis.removeClass("ac_over");

		$(lis[active]).addClass("ac_over");
	}

	function selectCurrent() 
	{
		var li = $("li.ac_over", results)[0];
		
		if (!li)
		{
			var $li = $("li", results);
		}
		
		if (li) 
		{
			selectItem(li);
			return true;
		}
		else 
		{
			return false;
		}
	}

	function selectItem(li) 
	{
		if (!li) 
		{
			li = document.createElement("li");
			li.extra = [];
			li.selectValue = "";
		}
		
		var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);		
		input.lastSelected = v;
		prev = v;
		$results.html("");
		$input.val(v);
		hideResults();
		
		if (options.onItemSelect)
		{
			setTimeout(function() { options.onItemSelect(li) }, 1);
		}			
	}

	function showResults() 
	{
		var pos    = findPos(input);
		var iWidth = $input.width();

		$results.css({
			width: parseInt(iWidth) + "px",
			top: (pos.y + input.offsetHeight) + "px",
			left: pos.x + "px"
		}).show();
	}

	function hideResults() 
	{
		setTimeout(hideResultsNow, 200);
	}

	function hideResultsNow() 
	{
		if ($results.is(":visible")) 
		{
			$results.hide();
			active = -1;
		}
	}

	function buildDom(data) 
	{
		var ul = document.createElement("ul");
		var num = data.length;

		for (var i=0; i < num; i++) 
		{
			var row = data[i];

			if (!row) continue;
			
			var li = document.createElement("li");
			
			if (options.formatItem) 
			{
				li.innerHTML = options.formatItem(row, i, num);
				li.selectValue = row[0];
			} 
			else 
			{
				li.innerHTML = row;
				li.selectValue = row;
				
				$(li).highlight($(input).val());
			}
			
			var extra = null;
			
			if (row.length > 1) 
			{
				extra = [];
				
				for (var j=1; j < row.length; j++) 
				{
					extra[extra.length] = row[j];
				}
			}
			
			li.extra = extra;
			ul.appendChild(li);

			$(li).hover(
				function() 
				{ 
					$("li", ul).removeClass("ac_over"); 
					$(this).addClass("ac_over"); 
					active = $("li", ul).indexOf($(this).get(0)); 
				},
				function() 
				{ 
					$(this).removeClass("ac_over"); 
				}
			).click(function(e) 
			{ 
				e.preventDefault(); 
				e.stopPropagation(); 
				selectItem(this);				
				hideResultsNow();
				$("#prodfind").submit();
			});
		}
		
		return ul;
	}

	function matchSubset(s, sub) 
	{
		s = s.toLowerCase();
		var i = s.indexOf(sub);
		
		if (i == -1) 
		{
			return false;
		}
		
		return i == 0 || options.matchContains;
	}

	function findPos(obj)
	{
		var curleft = obj.offsetLeft || 0;
		var curtop  = obj.offsetTop  || 0;
		
		while (obj = obj.offsetParent) 
		{
			curleft += obj.offsetLeft
			curtop  += obj.offsetTop
		}
		
		return {x:curleft,y:curtop};
	}
}

jQuery.fn.autocomplete = function(url) 
{
	options                = {};
	options.url            = url;
	options.resultsClass   = options.resultsClass  || "ac_results";
	options.matchSubset    = options.matchSubset   || 1;
	options.matchContains  = options.matchContains || 0;

	this.each(function() 
	{
		new jQuery.autocomplete(this, options);
	});

	return this;
}

jQuery.fn.indexOf = function(e)
{
	for(var i=0; i<this.length; i++)
	{
		if( this[i] == e) 
		{
			return i;
		}
	}
	
	return -1;
}

jQuery.fn.highlight = function(pattern) 
{
	function innerHighlight(node, pattern) 
	{
		var skip = 0;
		
		if (node.nodeType == 3) 
		{
			var pos = node.data.toUpperCase().indexOf(pattern);
			
			if (pos >= 0) 
			{
				var spannode = document.createElement('span');
				
				spannode.className = 'highlightSelection';
				var middlebit      = node.splitText(pos);
				var endbit         = middlebit.splitText(pattern.length);
				var middleclone    = middlebit.cloneNode(true);
				
				spannode.appendChild(middleclone);
				middlebit.parentNode.replaceChild(spannode, middlebit);
				
				skip = 1;
			}
		}
		else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) 
		{
			for (var i = 0; i < node.childNodes.length; ++i) 
			{
				i += innerHighlight(node.childNodes[i], pattern);
				
				if (i > 1000)
				{
					return;
				}
			}
		}
		
		return skip;
	}
	return this.each(function() 
	{
		innerHighlight(this, pattern.toUpperCase());
	});
};

jQuery.fn.removeHighlight = function() 
{
	return this.find("span.highlightSelection").each(function() 
	{
		this.parentNode.firstChild.nodeName;
		
		with (this.parentNode) 
		{
			replaceChild(this.firstChild, this);
			normalize();
		}
	}).end();
};

