/* BLIP.History
 *
 * A way to abstract out history changes. Abstracts to the same interface as HTML5 history, but
 * takes care of IE6&7's lack of .onHashChange event, and everybody else's lack of true HTML5 history
 *
 * usage:
 *
 *   var myHistoryObject = BLIP.History.create(function(state) { handleHistoryChange(state); });
 *
 */

BLIP.Class.createSingleton("BLIP.History", BLIP.Object, function(config) {
	},

	{
		create : function (onPopStateCallback) {
			// logic here to decide between html5 and onhashchange
			var HistoryToCreate = window.history && window.history.pushState ? BLIP.Html5History : BLIP.LegacyHistory;
			return new HistoryToCreate({
					onPopStateCallback : onPopStateCallback
			});
		}
	}
);



BLIP.Class.create("BLIP.Html5History", BLIP.Object, function(config) {
		this.onPopStateCallback = config.onPopStateCallback;
		window.onpopstate = this.delegate(this.onPopState);
	},
	{
		pushState : function(state, title, url) {
			window.history.pushState(state, title, url);
		},
		onPopState : function(event) {
			this.onPopStateCallback(event.state);
		}
	}
);

BLIP.Class.create("BLIP.LegacyHistory", BLIP.Object, function(config) {
		this.cachedStates = {};
		this.onPopState = config.onPopStateCallback;
		$(window).bind("hashchange", this.delegate(this.onHashChange));
	},

	{
		onHashChange : function() {
			if(this.skipNextChange) {
				this.skipNextChange = false;
				return;
			}
			var currentHash = window.location.hash;
			if(this.cachedStates[currentHash]) {
				this.goToHistoryState(this.cachedStates[currentHash].state);
			}
			else {
				this.goToHistoryState(null);
			}
		},
		goToHistoryState : function (state) {
			this.onPopState(state);
		},
		pushState : function(state, title, url) {
			this.cachedStates["#!"+url] = {
				state : state,
				title : title,
				url : url
			};
			this.skipNextChange = true;
			window.location.hash = "!"+url;
		}
	}
);

