/*
 * Google Search 1.0
 *
 * Created by Stephen Hallgren (aka Teevio)
 * http://teevio.com
 * 
 * Quality control by JSLint
 * http://www.jslint.com/
 * 
 */

googleSearch = {
	resultsContainerId: 'googleSearchResults',
	resultsListId: 'googleResultsList',
	logoId: 'googleLogo',
	loadingId: 'googleSearchLoading',
	loadingGraphicId: 'googleSearchLoadingGraphic',
	scripTag: '',
	refreshTimeout: '',
	currentSearchTerm: '',
	baseApiUrl: 'http://ajax.googleapis.com/ajax/services/search/',
	loadedScripts: [],
	args: {
		type: "web",
		limit: 8,
		domain: false,
		safeSearch: true,
		keyword: ""
	},
	init: function(args)
	{
		// Assign passed args to object
		for (var key in args)
		{
			if (typeof args[key] !== 'function')
			{
				this.args[key] = args[key];
			}
		}
				
		this.buildHtml();
	},
	buildHtml: function()
	{
		$(document).ready(function()
		{
			$('#'+googleSearch.args.id).click(function(event)
			{
				event.stopPropagation();
			});
			$('#'+googleSearch.args.id).focus(function()
			{
				googleSearch.currentSearchTerm = this.value;
				
				if (this.value != '')
				{
					$('#'+googleSearch.resultsContainerId).show();	
				}
			});

			$(document).click(function(event)
			{
				if ($(event.target).parents('#'+googleSearch.resultsContainerId).length <= 0)
				{
					$('#'+googleSearch.resultsContainerId).hide();						
				}
			});

			$('#'+googleSearch.args.id).keyup(function()
			{
				googleSearch.inputSearch(this);
				return false;
			});	
			
			$('#'+googleSearch.args.id).closest("form").submit(function()
			{
				return false;
			});
		});
		
		output = '<div id="'+googleSearch.resultsContainerId+'">';
		output += '</div>';
		
		$('body').prepend(output);
		
		var searchHeight = $('#'+this.args.id).height();
		var searchWidth  = $('#'+this.args.id).width();
		var searchOffset = $('#'+this.args.id).offset();

		var offsetLeft = searchOffset.left - $('#'+googleSearch.resultsContainerId).width()/2 + searchWidth/2;
		
		$('#'+googleSearch.resultsContainerId).css({top: searchOffset.top+searchHeight+5, left: offsetLeft});
		
		if (this.args.keyword != '')
		{
			this.search();		
		}
	},
	search: function()
	{
		this.currentSearchTerm = this.args.keyword;
			
		this.showLoading();

		var limit      = this.args.limit;
		var keyword    = '';
		var safeSearch = '&safe=moderate';
		var siteSearch = '';

		if (!this.args.keyword && !this.args.fromUser)
		{
			return false;
		}
		
		if (false == this.args.safeSearch)
		{
			safeSearch = '&safe=off';
		}	
		
		keyword = '&q='+this.args.keyword;
		
		if (this.args.domain != '')
		{
			keyword = keyword + ' site:'+this.args.domain;
		}		
		
		url = this.baseApiUrl + this.args.type + "?v=1.0"+keyword+"&key="+this.args.apiKey+"&callback=googleSearch.search_cb&rsz=large";

		this.callCount    = 1;
		this.currentCount = 0;
		
		if (this.args.limit > 8)
		{
			this.callCount    = Math.ceil(this.args.limit / 8);
			this.callsPending = this.callCount;
		}
		
		for (var i = 0; i < this.callCount; i++)
		{
			this.addScript(url+'&start='+(i*8));	
		}

		this.search_cb = function (result)
		{				
			if (result.responseStatus == 200)
			{
				if (this.args.type == 'image')
				{
					this.buildImageResults(result);
				}
				else
				{
					this.buildResults(result);	
				}				
			}
			else
			{
				// an error occurred
			}
			
			this.hideLoader();
		};
	},
	inputSearch: function()
	{
		if ($('#'+this.args.id).val() == '')
		{
			$('#'+googleSearch.resultsContainerId).hide();	
		}
		else if (this.currentSearchTerm != $('#'+this.args.id).val())
		{		
			$('#'+googleSearch.resultsContainerId).show();
			clearTimeout(window.searchFieldTimeout);
			window.searchFieldTimeout = window.setTimeout("googleSearch.inputSearchTimeout()", 500);         

			window.clearTimeout(window.refreshTimeout);	
			this.showLoading();
		}
	},
	showLoading: function()
	{
		$('#'+googleSearch.resultsContainerId).html('<div id="'+googleSearch.loadingId+'"><div id="'+googleSearch.loadingGraphicId+'"></div><div id="'+googleSearch.logoId+'"><a href="http://www.google.com" title="powered by" target="_blank">powered by</a></div></div>');
	},
	inputSearchTimeout: function()
	{
		clearTimeout(window.searchFieldTimeout);

		if ($('#'+this.args.id).val() !== '')
		{
			this.args.keyword  = $('#'+this.args.id).val();
			this.sinceId       = '';
			this.sinceSearchId = '';
			
			this.search();		
		}	
	},
	buildResults: function(results)
	{
		var output = '';
		
		if ($('#'+googleSearch.resultsListId).length <= 0)
		{
			var noresults = '';
			
			if (results.responseData.results.length <= 0)
			{
				noresults = 'noresults';
			}
			
			output += '<ul id="'+googleSearch.resultsListId+'" class="'+noresults+'">';
			if (results.responseData.results.length <= 0)
			{
				output += '<li class="top"><p title="No Results"><span>No Results</span></p></li>';
			}
			output += '</ul>';
			output += '<div id="'+googleSearch.logoId+'"><a href="http://www.google.com" target="_blank" title="powered by">powered by</a></div>';
			$('#'+googleSearch.resultsContainerId).append(output);	
		}
		
		var output = '';
		
		for (var i = 0; i < results.responseData.results.length; i++)
		{
			result    = results.responseData.results[i];
			className = '';

			if (this.currentCount >= this.args.limit)
			{
				this.removeScript();
				continue;
			}
			
			this.currentCount++;
			
			if (i == 0 && this.currentCount == 1)
			{
				className += 'top ';
			}
		
			if (i % 2 == 1)
			{
				className += 'odd ';
			}
			
			
			var titleNoFormat   = result.titleNoFormatting;
			var contentNoFormat = this.stripHTML(result.content);

			
			if (titleNoFormat.length > 23)
			{
				titleNoFormat = titleNoFormat.substr(0,23)+ ' &hellip;';
			}
			
			if (contentNoFormat.length > 35)
			{
				contentNoFormat = contentNoFormat.substr(0,35)+ ' &hellip;';
			}
			
			this.regExp = new RegExp('('+this.currentSearchTerm+')', "gi");
			
			var title   = titleNoFormat.replace(this.regExp, '<b>$1</b>');
			var content = contentNoFormat.replace(this.regExp, '<b>$1</b>');

		
			output += '<li class="' + className + '" onclick="window.location.href=\''+result.url+'\'">';
			output += '<div class="favicon"><img src="http://www.google.com/s2/favicons?domain='+result.visibleUrl+'"></div>';
			output += '<h1 title="'+titleNoFormat+'"><span>'+title+'</span></h1>';
			output += '<p title="'+contentNoFormat+'"><span>'+content+'</span></p>';
			output += '<p title="'+result.visibleUrl+'"><a href="'+result.url+'"><span>'+result.visibleUrl+'</span></a></p>';
			output += '</li>';
		}

		$('#'+googleSearch.resultsListId).append(output);	
	},
	buildImageResults: function(results)
	{
		output = '';

		for (var i = 0; i < results.responseData.results.length; i++)
		{
			if (this.currentCount >= this.args.limit)
			{
				this.removeScript();
				continue;
			}
			
			this.currentCount++;
			
			result = results.responseData.results[i];
			
			output += '<img src="'+result.tbUrl+'">';
		}

		$('#'+googleSearch.resultsContainerId).append(output);	
	},
	addScript: function(url)
	{
		$('head:first').append($('<script type="text/javascript" src="'+url+'"></script>'));
		
		this.loadedScripts.push(url);
	},
	removeScript: function()
	{
		$('script').each(function(i)
		{
			$scriptTag = $(this);
			
			for (var j = 0; j < googleSearch.loadedScripts.length; j++)
			{
				if ($scriptTag.attr('src') == googleSearch.loadedScripts[j])
				{
					$scriptTag.remove();

					delete googleSearch.loadedScripts[j];
				}
			}
		});
	},
	hideLoader: function()
	{
		$('#'+googleSearch.loadingId).hide();
	},
	stripHTML: function (oldString)
	{
		oldString = oldString.replace(/&(lt|gt);/g, function (strMatch, p1){
			return (p1 == "lt")? "<" : ">";
		});
		return oldString.replace(/<\/?[^>]+(>|$)/g, "");
	}
};
