// Much of this code was found and modified from Ajax History by Taku Sano

(function($){
$.history = new function(){

	var _currentHash;
	var _intervalId;
	var _listener;

	var _initialize = function(){};
	var _update = function(){};
	var _observeHistory = function(){};

	this.getCurrentHash = function(){
		return _currentHash;
	};

	this.update = function(hash){
		hash = hash.replace('#', '');
		if (hash != _currentHash) {
			_currentHash = hash;
			_update(_currentHash);
		}
	};

	if ($.browser.msie) {

		var historyIframe;

		_initialize = function(){
			historyIframe = $('<iframe style="display: none;"></iframe>').prependTo(document.body).get(0);
			var iframe = historyIframe.contentWindow.document;
			iframe.open();
			iframe.close();
			iframe.location.hash = _currentHash;
		};

		_update = function(hash){
			location.hash = hash;
			var iframe = historyIframe.contentWindow.document;
			iframe.open();
			iframe.close();
			iframe.location.hash = hash;
		};

		_observeHistory = function(){
			var hash = historyIframe.contentWindow.document.location.hash.replace('#', '');
			if (hash != _currentHash) {
				_currentHash = hash;
				location.hash = _currentHash;
				_listener(_currentHash);
			}
		};

	} else if ($.browser.mozilla || $.browser.opera) {

		_update = function(hash){
			location.hash = hash;
		};

		_observeHistory = function(){
			var hash = location.hash.replace('#', '');
			if (hash != _currentHash) {
				_currentHash = hash;
				_listener(_currentHash);
			}
		};

	} else if ($.browser.safari) {

		var backStack, forwardStack;
		var delayCheck;

		_initialize = function(){
			backStack = [];
			backStack.length = history.length;
			forwardStack = [];
			delayCheck = false;
		};

		_update = function(hash){
			backStack.push(hash);
			forwardStack.length = 0;
			delayCheck = true;
			// Wait a while before allowing checking so that Safari has time to update the "history" object
			// correctly (otherwise the check loop would detect a false change in hash).
			setTimeout(function(){
				delayCheck = false;
			}, 200);

			var a = $('<a>').attr('href', '#' + hash).get(0);			var evt = document.createEvent('MouseEvents');			evt.initEvent('click', true, true);			a.dispatchEvent(evt);
		};

		_observeHistory = function(){
			if (!delayCheck) {
				var delta = history.length - backStack.length;

				if (delta) { // back or forward button has been pushed
					if (delta < 0) { // back button has been pushed
						for (var i = 0; i < Math.abs(delta); i++)
							forwardStack.unshift(backStack.pop()); // move items to forward stack
					} else { // forward button has been pushed
						for (var i = 0; i < delta; i++)
							backStack.push(forwardStack.shift()); // move items to back stack
					}
				    _currentHash = backStack[backStack.length - 1] || _getSafariHash();
				    _listener(_currentHash);
				}
			}
		};

	}
	
	var _getSafariHash = function(){
		var url = document.URL;
		return url.indexOf('#') >= 0 ? url.split('#')[1] : '';
	};

	this.initialize = function(callback){
		if ($.isFunction(callback)) {
			_listener = callback;
			_currentHash = $.browser.safari ? _getSafariHash() : location.hash.replace('#', '');
			_initialize();
			if (_currentHash.length > 0)
				_listener(_currentHash);
			_intervalId = setInterval(_observeHistory, 200);
		}
	};

};
})(jQuery);