/**
 * 
 */
(function($){
	$.jhistory = {};
	
	var defaultvar = 'a1';
	var hashIndex = 0;
	
	$.jhistory.setVar = function (varName, value) {
		var jhistory = $("body").data("JHistory");	
		if (typeof value != 'undefined' && value != null) {
			jhistory[varName] = value;
		} else {
			jhistory[varName] = 0;
		}
		sort();
		generateFragment();
		$.jhistory.notifyListeners();
	}
	
	$.jhistory.delVar = function (varName) {
		var jhistory = $("body").data("JHistory");
		delete jhistory[varName];
		generateFragment();
		$.jhistory.notifyListeners();
	}
	
	$.jhistory.registerListener = function (callbackFunction) {
		var listeners = $("body").data("JHistoryListeners");
		if ($.inArray(callbackFunction, listeners) < 0) {
			listeners.push(callbackFunction);
		}
	}
	
	$.jhistory.removeListener = function (callbackFunction) {
		var listeners = $("body").data("JHistoryListeners");
		listeners = $.grep(listeners, function (a) {return a != callbackFunction});
		$("body").data("JHistoryListeners", listeners);
	}
	
	$.jhistory.notifyListeners = function (initial) {
		var listeners = $("body").data("JHistoryListeners");
		var data = $("body").data("JHistory");
		for (var i = 0; i < listeners.length; i++) {
			listeners[i](data, initial);
		}
	}
	
	_historyUpdater = function () {	
		if (getFragment() != $("body").data("JHistoryFragment")) {
			fragmentChanged();
		}
	}
	
	var generateFragment = function () {
		var jhistory = $("body").data("JHistory");
		var fragment = '';
		var tmpvals = new Array();
		for (value in jhistory) {
			if (jhistory[value] != null && jhistory[value] != 0) {
				tmpvals.push(value+"="+jhistory[value]);
			} else {
				tmpvals.push(value);
			}
		}	
		if (tmpvals.length == 0) {
			if (getFragment() == '') {
				fragment = "";
			} else if (getFragment() == '#') {
				fragment = "#";
			} else {
				fragment = "#"+this.defaultVal;
			}
		} else {
			fragment = "#"+tmpvals.join("&");
		}
		
		$("body").data("JHistoryFragment", fragment);
		if (fragment.length > 0) {
			window.location.href = cleared()+fragment;
		}
		if ($.browser.msie) {
			var iframe = $("#history_iframe")[0].contentWindow.document;
			iframe.open();
			iframe.close();
			iframe.location.hash = fragment;

		}

	}
	
	var fragmentChanged = function () {
		parseFragment();
		generateFragment();
		$.jhistory.notifyListeners(true);
	}
	
	var getFragment = function () {
		var pos = window.location.href.search("#");
		if (pos > 0) {
			return window.location.href.substr(pos);
		} else {
			return "";
		}
	}
	
	var sort = function () {
		var tmparray = new Array();
		var jhistory = $("body").data("JHistory");
		var jhistorySorted = {};
		for (val in jhistory) {
			tmparray.push(val);
		}
		tmparray = tmparray.sort();
		for (var i = 0; i < tmparray.length; i++) {
			jhistorySorted[tmparray[i]] = jhistory[tmparray[i]];
		}
		var jhistory = $("body").data("JHistory", jhistorySorted);
	}
	
	var cleared = function () {
		return window.location.href.substr(0, window.location.href.search("#"));
	}
	
	var parseFragment = function () {
		var fragment = getFragment();
		var jhistory = {};
		fragment = fragment.substr(1);
		if (fragment.length > 0 && fragment != $.jhistory.defaultVal) {
			var tmpdata = fragment.split("&");
			for (var i = 0; i < tmpdata.length; i++) {
				var parts = tmpdata[i].split("=");
				if (parts.length > 1) {
					jhistory[parts[0]] = parts[1];
				} else {
					jhistory[parts[0]] = null;
				}
			}
		}
		$("body").data("JHistory", jhistory);
	}
	
	$(document).ready(function() {
		var fragment = new Array();
		var listeners = new Array();
		$("body").data("JHistory", fragment);
		$("body").data("JHistoryListeners", listeners);	
		parseFragment();
		setInterval("_historyUpdater()", 200);
		if ($.browser.msie) {
			$("body").prepend('<iframe id="history_iframe" style="display: none"></iframe>');
			var iframe = $("#history_iframe")[0].contentWindow.document;
			iframe.open();
			iframe.close();
		}
	});
	
})(jQuery);
