/*	Copyright 2007-2008 Amit Jain, please email amit_jain_@yahoo.com if you want to use whole or part of this file
*/

function WebSearch(searchPhrase, stringGenerator, language, searchListContainer, nResults, scriptID)
{
	if (/^[\s\u00A0\u2003]*$/.test(searchPhrase) === 0)	// nothing to search
		return;

	this.lastQuery = searchPhrase;
	this.lastResultCount = 0;
	this.lastDomain = this.lastRegion = "";
	this.nResults = nResults || 10;
	this.searchScriptElementID = scriptID || "yahoo_web_search_script";
	this.searchUrl = ['http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=SahajSearch', 
							'http://api.search.yahoo.com/NewsSearchService/V1/newsSearch?appid=SahajSearch'];
	this.stringGen = stringGenerator;
	this.displayContainer = searchListContainer || document.body;	// spec says doc.body is always present, regardless of markup
	this.language = language;	// not used right now but Yahoo api does give the option of constraing searches to pages in a given language
		
	this.resultsDisplayHeader = this.displayContainer.firstChild;
	if (!this.resultsDisplayHeader || this.resultsDisplayHeader.id != 'resultsDisplay_header') {
		var targetDoc = this.displayContainer.ownerDocument;
		if (searchListContainer)
			searchListContainer.innerHTML = "";
			
		this.resultsDisplayHeader = targetDoc.createElement("span");
		this.resultsDisplayHeader.id = 'resultsDisplay_header';
		this.resultsDisplayHeader.className = 'search_header';
		this.displayContainer.appendChild(this.resultsDisplayHeader);

		this.resultsDisplayList = targetDoc.createElement("ul");
		this.resultsDisplayList.id = 'resultsDisplay_list';
		this.resultsDisplayList.className = 'search_list';
		this.displayContainer.appendChild(this.resultsDisplayList);
	}
	else {
		this.resultsDisplayList = this.resultsDisplayHeader.nextSibling;
		this.resultsDisplayList.innerHTML = this.resultsDisplayHeader.innerHTML = "";
	}

	this.doWebSearch();
}

WebSearch.KickOff = function(container, wsparams) {
	if (wsparams || (opener && opener.websearchParams)) {
		var wsp = wsparams || opener.websearchParams;
		document.title = wsp.title + " - " + wsp.stringsGen('websearch_results_results');
		WebSearch._docHolder = new WebSearch(wsp.string, wsp.stringsGen, wsp.lang, container, wsp.nResults || 10);
	}
	else
		throw new Error("I can only be a pop-up, and opener should expose a websearchParams object");
};

WebSearch.KickOffAuto = function(input, container, nResults) {
	var _strings_table = {
		websearch_results_searching: "searching the web&hellip;",
		websearch_results_prev: "previous",
		websearch_results_next: "next",
		websearch_results_results: "search results"
	};
	
	if ((typeof input).toLowerCase() == "string")
		input = document.getElementById(input);
	
	if ((typeof container).toLowerCase() == "string")
		container = document.getElementById(container);
		
	if (input && input.value.match(/\S+/)) {
		WebSearch._docHolder = new WebSearch(input.value, function(s) { return _strings_table[s]; }, input.lang, container, nResults || 25);
	}
};

WebSearch.Cleanup = function() {
	WebSearch._docHolder = null;
};

WebSearch.prototype.doWebSearch = function()
{
	var startingRecord = "";
	if (this.lastResultCount > 0)
		startingRecord = "&start=" + (this.lastResultCount + 1);
		
	var restrictDomain = "";
	if (this.lastDomain.length > 0)
		restrictDomain = "&site=" + this.lastDomain;

	var nResultsWanted = "&results=" + this.nResults;
	//var regionCode = "&region=" + this.stringGen('websearch_region_code');
	var query = "&query=" + "\"" + this.lastQuery + "\"";
	var url = this.searchUrl[0] + query + startingRecord + restrictDomain + nResultsWanted + "&output=json&callback=document.webSearcher.processSearchResults";
	document.webSearcher = this;	// loading of JSON script might happen asynch or synch - so I am being doubly safe
	
	this.executeSearch(url);
};

WebSearch.prototype.incrementalWebSearch = function(backwards)
{
	if (backwards)
		this.lastResultCount = Math.max(this.lastResultCount - 2 * this.nResults, 0);
		
	this.doWebSearch();
}

WebSearch.summarizeText = function(str, len)
{
	var strLen = str.length;
	if (len < 2 || str.length <= len)
		return str;
		
	len /= 2;
	return str.substr(0, len) + '\u2026' + str.substr(strLen - len);
}

WebSearch.prototype.executeSearch = function(url)
{
	this.resultsDisplayHeader.innerHTML = "\u3010" + WebSearch.summarizeText(this.lastQuery, 32) + "\u3011 : " + this.stringGen('websearch_results_searching').blink();
	this.displayContainer.style.display = "";	// it can be hidden to start with
	//this.resultsDisplayList.style.display = "none";

	var scriptElemContainer, targetDoc = this.displayContainer.ownerDocument;
	var scriptElem = targetDoc.getElementById(this.searchScriptElementID);
	if (scriptElem) {
		scriptElemContainer = scriptElem.parentNode;
		scriptElemContainer.removeChild(scriptElem);
		delete scriptElem;
	}
	else
		scriptElemContainer = targetDoc.getElementsByTagName("head")[0];

	scriptElem = targetDoc.createElement("script");
	scriptElem.id = this.searchScriptElementID;
	scriptElem.setAttribute("type", "text/javascript");
	scriptElem.setAttribute("charset", "utf-8");
	scriptElem.setAttribute("src", url);
	scriptElemContainer.appendChild(scriptElem);	// this will execute the url
};

WebSearch.onLinkClick = function(e)
{
	if (this.href) {	// 'this' refers to the target of the click
		if (!e)
			e = window.event;
			
		window.open(this.href, this.target);
		
		if (e.preventDefault)
			e.preventDefault();
		else
			e.returnValue = false;
	}	
}

WebSearch.prototype.processSearchResults = function(r)
{
	var resultSet = r.ResultSet, a;
	var startResultsPos = parseInt(resultSet.firstResultPosition);	// 1-based
	var totalResults = parseInt(resultSet.totalResultsReturned), totalResultsAvailable = parseInt(resultSet.totalResultsAvailable);
	
	var header = this.resultsDisplayHeader, targetDoc = this.displayContainer.ownerDocument;
	{
		header.innerHTML = "";
		if (this.lastResultCount > 0) {
			a = targetDoc.createElement("a");
			a.innerHTML = "\u21DC";
			a.title = this.stringGen('websearch_results_prev') + " " + Math.min(this.lastResultCount, this.nResults);
			a.href = "javascript:document.webSearcher.incrementalWebSearch(true)";
			a.style.display = "block";
			a.style.cssFloat = a.style.styleFloat = "left";	// IE supports styleFloat
			a.style.paddingLeft = "5px";
			a.style.fontSize = "xx-large";
			a.style.lineHeight = 0.5;
			header.appendChild(a);
		}
		
		this.lastResultCount = (startResultsPos - 1) + totalResults;
		if (totalResultsAvailable > this.lastResultCount + 1) {
			a = targetDoc.createElement("a");
			a.innerHTML = "\u21DD";
			a.title = this.stringGen('websearch_results_next') + " " + Math.min(totalResultsAvailable - this.lastResultCount, this.nResults);
			a.href = "javascript:document.webSearcher.incrementalWebSearch(false)";
			a.style.display = "block";
			a.style.cssFloat = a.style.styleFloat = "right";	// IE supports styleFloat
			a.style.paddingRight = "5px";
			a.style.fontSize = "xx-large";
			a.style.lineHeight = 0.5;
			header.appendChild(a);
		}
		
		{
			a = targetDoc.createElement("div");
			a.innerHTML = "\u3010" + WebSearch.summarizeText(this.lastQuery, 32) + "\u3011 : " + this.stringGen('websearch_results_results') + "&nbsp;" + startResultsPos + "-" + (startResultsPos + totalResults - 1);
			a.style.margin = "auto";
			header.appendChild(a);
		}
	}
	
	var ul = this.resultsDisplayList;
	ul.innerHTML = "";
	var pattern = new RegExp(this.lastQuery, "g"), repl = "<b>$&</b>";
	for (var i = 0; i < totalResults; ++i) {
		var li = targetDoc.createElement("li");
		{
			var result_i = resultSet.Result[i];
			a = targetDoc.createElement("a");
			a.innerHTML = WebSearch.summarizeText(result_i.Title, 64);
			a.href = result_i.Url;
			a.target = "_blank";	// open in new window, each link going to the same window
			a.title = result_i.Url;
			a.className = "search_result_link";
			//attach_event(a, "click", WebSearch.onLinkClick);	// get around browsers inhibiting links in new window
			li.appendChild(a);
			
			var p = targetDoc.createElement("div");
			p.innerHTML = result_i.Summary.replace(pattern, repl);
			p.className = "search_result_summary";
			li.appendChild(p);
		}
		ul.appendChild(li);
	}
	
	//ul.style.display = "";	// was hidden at the start of executeSearch
	
	/* should not remove script here because this function is called from that script. Duh. Ff copes with it, though.
	var scriptElem = this.targetDoc.getElementById(this.searchScriptElementID);	// remove the script element
	if (scriptElem) {
		var head = scriptElem.parentNode;
		head.removeChild(scriptElem);
		delete scriptElem;
	}
	*/
	//var scriptElem = targetDoc.getElementById(this.searchScriptElementID);	// remove the script element
	//if (scriptElem)
	//	setTimeout(function(){ scriptElem.parentNode.removeChild(scriptElem); }, 1);		// closure
};
