// fading options
gv_startShade = [255,253,67]; // yellowish
gv_endShade = [238, 238, 238]; // page background
gv_frames = 50; // length of animation /20ms

function SearchControl (placeholder) {
	var o = this;
	o.searchInput = document.getElementById('searchInput');
	o.isTroll = (o.searchInput.className.indexOf('troll') == -1) ? false : true;
	o.placeholder = (placeholder != null) ? placeholder : 'Search';
	o.searchResultsDL = document.getElementById('searchResultsDL');
	o.searcher = new google.search.WebSearch();
	o.searcher.setNoHtmlGeneration();
	o.searcher.setResultSetSize(google.search.Search.SMALL_RESULTSET);
	o.searcher.setSiteRestriction("prateekrungta.com");
	o.searcher.setSearchCompleteCallback(o, SearchControl.prototype.searchComplete, [o.searcher]);
	o.status = new StatusControl();
	
	if (o.isTroll) {
		o.searchInput.value = o.placeholder;
		o.searchInput.style.color = '#808080';
		o.searchInput.onfocus = function () {
			if (o.searchInput.value == o.placeholder) {
				o.searchInput.value = '';
				o.searchInput.style.color = '#000';
			}
		};
	}

	o.searchInput.onkeyup = function () { o.getQuery(); };
	o.searchInput.onblur = function () {
		if (o.searchInput.value == '') {
			roll(o.searchResultsDL, 0);
			o.query = '';
			if (o.isTroll) {
				o.searchInput.value = o.placeholder;
				o.searchInput.style.color = '#808080';
			}
		}
	};
	
	o.pageLinks = document.getElementsByTagName('a');
	o.mouseOverEffects = (window.scrollDown) && (o.pageLinks.length > 0);
	o.pageLinksDOM = new Object();
	for (var i = o.pageLinks.length - 1; i >= 0; i--) {
		var url = o.pageLinks[i].href;
		url = url.replace("http://","");
		// for local urls
		// url = url.replace("", "");
		var levels = url.split('/');
		var plDOM = o.pageLinksDOM;
		for (var j=0; j < levels.length; j++) {
			if (!plDOM[levels[j]]) plDOM[levels[j]] = new Object();
			if (j == levels.length-1) plDOM[levels[j]].link = o.pageLinks[i];
			else {
				if(!plDOM[levels[j]].pages) plDOM[levels[j]].pages = new Object();
				plDOM = plDOM[levels[j]].pages;
			}
		}
	}
	o.status.typeAndEraseMessage('Initialized');
}

SearchControl.prototype.getQuery = function (e) {
	var o = this;
	if (!o.query || (o.query && o.query != o.searchInput.value)) {
		o.query = o.searchInput.value;
		if (o.searchTimer) clearTimeout(o.searchTimer);
		o.searchTimer = setTimeout(function () { o.executeSearch(); }, 1000);
	}
}

SearchControl.prototype.executeSearch = function () {
	var o = this;
	if (o.query && o.query != '') {
		o.searcher.execute(o.query);
		o.status.typeAndKeepAlive('Searching');
	}
}

SearchControl.prototype.searchComplete = function (searcher) {
	var o = this;
	
	o.status.killAll();
	if (searcher.results.length == 0) o.status.writeAndEraseMessage('No results found.');
	else {
		var message = (searcher.results.length == 1) ? '1 match' : searcher.results.length + ' results.';
		o.status.writeAndEraseMessage(message);
	}

	var stagingDL = document.createElement('dl');
	stagingDL.style.position = 'absolute';
	stagingDL.style.visibility = 'hidden';
	o.searchResultsDL.parentNode.insertBefore(stagingDL, o.searchResultsDL);
	
	for (var i=0; i < searcher.results.length; i++) {
		var dt = document.createElement('dt');
		var dd = document.createElement('dd');
		var a = document.createElement('a');
		var p = document.createElement('p');

		a.innerHTML = searcher.results[i].titleNoFormatting;
		a.href = searcher.results[i].url;
		p.innerHTML = searcher.results[i].content.replace(/<([\/]?)b>/g, '<$1strong>');
		if (i == searcher.results.length-1) dd.className = 'last';

		if (o.mouseOverEffects) {
			// attaching the onmouseover scroll
			var isError = false;
			var plDOM = o.pageLinksDOM;
			var url = searcher.results[i].url;
			url = url.replace("http://","");
			var levels = url.split('/');
			for (var j=0; j < levels.length && !isError; j++) {
				if (!plDOM[levels[j]]) isError = true;
				else {
					if (plDOM[levels[j]].pages && j != (levels.length - 1)) plDOM = plDOM[levels[j]].pages;
					else plDOM = plDOM[levels[j]].link;
				}
			}
			if (!isError) {
				a._scrollTo = plDOM;
				a._fadeElement = plDOM.parentNode.parentNode;
				a.onmouseover = scrollDown;
			}
		}

		dt.appendChild(a);
		dd.appendChild(p);
		stagingDL.appendChild(dt);
		stagingDL.appendChild(dd);
	}

	cleanElement(o.searchResultsDL);
	roll(o.searchResultsDL, stagingDL.offsetHeight);
	while (stagingDL.firstChild) o.searchResultsDL.appendChild(stagingDL.firstChild);
	stagingDL.parentNode.removeChild(stagingDL);
}

function initSearch () {
	new SearchControl();
}

function StatusControl () {
	var o = this;
	o.stream = document.getElementById('searchStatus');
	o.stream.innerHTML = "&nbsp;";
	o.currentMessage = ' ';
	o.finalMessage = ' ';
	o.typing = null;
	o.typed = 0;
	o.erasing = null;
	o.erased = 0;
	o.onTypeComplete = null;
	o.keepingAlive = null;
	o.delay = 0;
	
	this.typeMessage = function (string) {
		kill();
		o.finalMessage = string;
		if (o.currentMessage != ' ') o.clearStream();
		o.typed = 0;
		o.typing = setTimeout(function(){type()}, 50);
	}
	
	this.eraseMessage = function () {
		kill();
		var string = '';
		while (string.length != o.currentMessage.length) { string += ' '; }
		o.finalMessage = string;
		if (o.currentMessage != ' ') {
			o.erased = 0;
			o.erasing = setTimeout(function(){erase()}, 25);
		}
		if (o.onTypeComplete == keepAlive) o.onTypeComplete = null;
	}
	
	this.typeAndEraseMessage = function (string) {
		o.onTypeComplete = o.eraseMessage;
		o.delay = 750;
		o.typeMessage(string);
	}
	
	this.typeAndKeepAlive = function (string) {
		o.onTypeComplete = keepAlive;
		o.delay = 50;
		o.typeMessage(string);
	}
	
	this.writeAndEraseMessage = function (string) {
		o.killAll();
		o.finalMessage = string;
		o.write(string);
		o.delay = 1250;
		var onTypeCompleteFunc = o.eraseMessage;
		o.keepingAlive = setTimeout(function(){onTypeCompleteFunc(); o.keepingAlive = null;}, o.delay);
	}
	
	this.clearStream = function () {
		o.write(' ');
	}
	
	this.write = function (string) {
		o.currentMessage = string;
		string = string.replace(/ /g, "&nbsp;");
		if (string == ' ' || string == '') string = "&nbsp;";
		o.stream.innerHTML = string;
	}
	
	function type() {
		o.write(o.finalMessage.substring(0, ++o.typed));
		if (o.typed != o.finalMessage.length) {
			o.typing = setTimeout(function(){type()}, 50);
		} else {
			o.typing = null;
			if (o.onTypeComplete) {
				var onTypeCompleteFunc = o.onTypeComplete;
				o.keepingAlive = setTimeout(function(){onTypeCompleteFunc(); o.keepingAlive = null;}, o.delay);
				o.onTypeComplete = null;
			}
		}
	}
	
	function erase() {
		o.write(o.finalMessage.substring(0, ++o.erased) + o.currentMessage.substr(o.erased));
		if (o.erased < o.finalMessage.length) {
			o.erasing = setTimeout(function(){erase()}, 50);
		} else {
			o.erasing = null;
			if (o.onTypeComplete) {
				var onTypeCompleteFunc = o.onTypeComplete;
				o.keepingAlive = setTimeout(function(){onTypeCompleteFunc(); o.keepingAlive = null;}, o.delay);
				o.onTypeComplete = null;
			}
		}
	}
	
	function keepAlive () {
		var aliveString = '.....';
		if (o.currentMessage.substr(o.finalMessage.length - aliveString.length) == aliveString) {
			// erase
			o.finalMessage = o.finalMessage.substr(0, o.finalMessage.length - aliveString.length);
			o.erased = o.finalMessage.length;
			while (o.finalMessage.length < o.erased + aliveString.length) { o.finalMessage += ' '; }
			o.erasing = setTimeout(function(){erase()}, 25);
		} else {
			// type
			o.finalMessage = o.currentMessage.replace(/ +$/, '');
			o.typed = o.finalMessage.length;
			o.finalMessage += aliveString;
			o.typing = setTimeout(function(){type()}, 50);
		}
		o.onTypeComplete = keepAlive;
		o.delay = 50;
	}
	
	function kill() {
		if (o.typing) { clearTimeout(o.typing); o.typing = null; }
		if (o.erasing) { clearTimeout(o.erasing); o.erasing = null; }
	}
	
	this.killAll = function  () {
		if (o.keepingAlive) { clearTimeout(o.keepingAlive); o.keepingAlive = null; }
		o.onTypeComplete = null;
		kill();
		o.clearStream();
		o.finalMessage = '';
	}
}

function cleanElement (e) {
	while (e.firstChild) e.removeChild(e.firstChild);
}

function roll (e, finalHeight) {
	// making it visible without a roll if browser doesn't support offsetHeight
	if (!e.offsetHeight && e.offsetHeight != 0) { 
		e.style.display = "";	
		return false; 
	}

	// making sure animation is not in progress
	if (e._currentlyRolling) { window.clearInterval(e._currentlyRolling); }
	
	e._start = e.offsetHeight;
	e._currentHeight = e._start;
	e._stop = finalHeight;
	e._frames = 25;
	e._frameRate = (e._start < e._stop) ? 1 : -1;
	e._currentFrame = (e._frameRate == 1) ? 0 : e._frames;

	if (e._start == e._stop) return false;
	
	e._currentlyRolling = window.setInterval(
			function () {
				var angle = (Math.PI / 2) * ((2 * e._currentFrame - e._frames) / e._frames);
				var slope = Math.round( Math.sin(angle) * 100) / 100;
				var diff = Math.abs(e._start - e._stop);
				var minima = (e._start < e._stop) ? e._start : e._stop;
				e._currentHeight = minima + (diff / 2) + Math.round(diff * slope / 2 );
				e._currentFrame += e._frameRate;	// moving the counter

				e.style.height	= e._currentHeight + "px";

				if (e._currentFrame > e._frames || e._currentFrame < 0)
				{
					window.clearInterval(e._currentlyRolling);
					e._currentlyRolling	= null;
				}
			},
			15 // the actual frame rate
		);
}
