/*
 * @description Display suggested terms from Google search
 * @return {jQuery Object}
 * @param {Object} options
 * @type {jQuery Plugin Method}
 * @author Mike Cravey
 * @version 0.1	
 */

;(function($) {
	$.fn.gSuggest = function(options) {
		var opts = $.extend(true, {}, $.fn.gSuggest.defaults, options);

		return this.each(function() {
			var $this = $(this);

			// Support for the Metadata Plugin.
			var o = $.meta ? $.extend(true, {}, opts, $this.data()) : opts;
			// Set the form to a public object that can be referenced from outside of this function
			$.fn.gSuggest.form = form = $this.closest('form');
			// Create the suggest box window and set it to a public object. Apply classes and attributes from defaults.
			$.fn.gSuggest.win = $('<div />').addClass(o.suggestBox.classes.join(' ')).attr(o.suggestBox.attrs);
			// Create the containing div with the label and append inside of the suggest box window
			$.fn.gSuggest.con = $('<div />').html('<h2>' + o.label + '</h2>').appendTo($.fn.gSuggest.win);
			// Create the list and append it inside the container
			$.fn.gSuggest.list = $('<ul />').appendTo($.fn.gSuggest.con);
			// Hide the suggest box window and then append it to the specified parent
			$.fn.gSuggest.win.hide().appendTo('#' + o.suggestBox.parentId);
			
			// Construct the search engine URL from params
			o.searchEngine.URL = o.searchEngine.URL + o.searchEngine.params;
			o.form.action = $.fn.gSuggest.form.attr('action');
			// Set the results URL. If not specified build it appropriately. Make it public so other things can get to it later.
			o.results.URL = '/' + lang + o.results.URL + '?q=';
			// Push all this stuff to the data object of the input in case it gets overwritten
			$this.data('o',o);
			$.fn.gSuggest.mOver = false;
						
			$this
				.keyup(function(e) {
					// Set this to the element that the action was committed against
					var $this = $(e.target);
					switch(e.keyCode)
					{
						// Enter
						case 13:
							break;
						// Esc
						case 27:
							$.fn.gSuggest.win.hide();
							break;
						// Up Arrow
						case 38:
							// If the focus object has been set
							if($.fn.gSuggest.focus) {
								// Set the focus object to the previous list item and give it the 'focus' class.
								$.fn.gSuggest.focus = $.fn.gSuggest.focus.removeClass('focus').prev('li').addClass('focus');
							} else {
								// Set the focus object to the last item in the list and give it the 'focus' class.
								$.fn.gSuggest.focus = $.fn.gSuggest.list.find('li:last').addClass('focus');
							}
							// Populate the input value with the text of the focused link
							$this.val($.fn.gSuggest.focus.text());
							return false;
							break;
						// Down Arrow
						case 40:
							// If the focus object has been set
							if($.fn.gSuggest.focus) {
								// Set the focus object to the next list item and give it the 'focus' class.
								$.fn.gSuggest.focus = $.fn.gSuggest.focus.removeClass('focus').next('li').addClass('focus');
							} else {
								// Set the focus object to the first item in the list and give it the 'focus' class.
								$.fn.gSuggest.focus = $.fn.gSuggest.list.find('li:first').addClass('focus');
							}
							// Populate the input value with the text of the focused link
							$this.val($.fn.gSuggest.focus.text());
							return false;
							break;
						// Any other key
						default:
							// Call the fetch method passing the current input
							$.fn.gSuggest.fetch($this);
							break;
					};
				})
				.blur(function(e){
					var $this = $(e.target);
					// If the mouseover flag is false
					if (!$.fn.gSuggest.mOver) {
						// Hide the suggestion box window
						$.fn.gSuggest.win.hide();
					}
				})
			;
			
			$.fn.gSuggest.list
				.mouseover(function(e) {
					$this = $(e.target);
					// When the mouse is over the suggestion box, set the mouseover flag to true (which keeps the blur on a click from hiding the box)
					$.fn.gSuggest.mOver = true;
					// Remove the focus class from all the list items
					$(this).find('li').removeClass('focus');
					// Set the focus to the hovered li
					$.fn.gSuggest.focus = $this.closest('li').addClass('focus');
				})
				// On mouseout set the mouseover flag to false
				.mouseout(function() {
					$.fn.gSuggest.mOver = false;
				})
				.click(function() {
					$.fn.gSuggest.form.submit();
				})
			;
		});

	// private function for debugging
	function debug($obj) {
		if (window.console && window.console.log) {
		window.console.log($obj);
		}
	}
};

$.fn.gSuggest.fetch = function(obj) {
	// Set a bunch of vars, notably, an empty array for building the list items, regex string based on the value of the input & the URL to send the term to for the suggested terms
	var $this = $(obj), x = 0, items = [], val = $this.val(), regex = new RegExp('(' + val + ')','g'),
		qURL = $this.data('o').searchEngine.URL + val;
	$.getJSON(qURL, function(json) {
		// For each of the results, build out the list elements
		$.each(json[1], function(i,v) {
			items[x++] = '<li><a href="';
			items[x++] = $this.data('o').results.URL;
			// Replace spaces in the search terms with '+'
			items[x++] = v[0].replace(/\s/g, '+');
			items[x++] = '">';
			// Wrap the text of the search term that matches the input value in a span tag which can be marked appropriately
			items[x++] = v[0].replace(regex, '<span>$1</span>');
			items[x++] = '</a></li>';
		});
		// Build the HTML for the list items by joining the array (faster than string concatenation)
		$.fn.gSuggest.list.html(items.join(''));
		// If there are items show the window, otherwise, don't
		if (items.length > 0) {
			$.fn.gSuggest.win.show();			
		} else {
			$.fn.gSuggest.win.hide();
		}
	});
}

// default options
$.fn.gSuggest.defaults = {
	label: 'Suggestions',
	searchEngine : {
		URL: 'http://google.com/complete/search',
		params: '?callback=?&output=json&q='
	},
	suggestBox : {
		parentId: 'TGOV_SF_Input',
		classes: ['gSuggest'],
		attrs: {
			id: 'suggestBox'
		}
	},
	results : {
		URL: '/search/Pages/results.aspx'
	},
	form: {}
};

})(jQuery);
