/*!
 * jQuery history API
 * 
 */
(function($,win){
  
	var history = win.history, fn_change;
	$.history = {};
	$.history.onchange = function(fn) {
		fn_change = fn;
	};
	$.history.trigger = function(state) {
		if (fn_change) {
			fn_change(state);
		}
	};
	if (history.pushState) {
		//cross-browser link fix
		if (location.hash) {
			var page = ('/' + location.hash.replace(/^#/,'')).replace(/^\/+/,'/');
			history.pushState({},document.title,page);
		}
		$.history.basePath = function() {
			return location.pathname;
		}
		$.history.getPage = function() {
			return location.pathname + location.search;
		}
		$.history.getQString = function() {
			var str = location.search.replace(/^\?/,'');
			return str ? fn_qsParse(str) : {};
		}
		$.history.changeState = function(state,title,url){
			history.pushState(state,document.title,url);
			$.history.trigger(state);
		};
		win.onpopstate = function(event) {
			//TODO: Determine why this event triggers on page load.
			if (event.state) {
				$.history.trigger(event.state);
			}
		};
	} else {
		//cross-browser link redirect
		if (location.pathname != '/' || location.search) {
			location.replace('/#' + location.pathname + location.search);
		}
		var states = {};
		$.history.basePath = function() {
			var str = location.hash.replace(/^#([^?]*)($|\?.*)/,'$1');
			return str.match(/^\//) ? str : '/' + str;
		}
		$.history.getPage = function() {
			var str = location.hash.replace(/^#/,'');
			return str.match(/^\//) ? str : '/' + str;
		}
		$.history.getQString = function() {
			var str = location.hash.replace(/^#([^?]*)\??/,'');
			return str ? fn_qsParse(str) : {};
		}
		$.history.changeState = function(state,title,url){
			location.href = '#' + ('/' + url).replace(/^\/+/,'/');
			states[url] = state;
		};
		$(window).hashchange(function(){
			var page = $.history.getPage(), state = states[page];
			$.history.trigger(state);
		});
	}
	
	function fn_qsParse(qs) {
		var arr = qs.split(/[?&]/), obj = {};
		$.each(arr,function(i,str){
			str.replace(/^([^=]+)(?:=(.*))?$/,function(str,key,val){
				if (val) {
					obj[fn_urlDec(key)] = fn_urlDec(val);
				} else {
					obj[fn_urlDec(key)] = '';
				}
			});
		});
		return obj;
	}
	function fn_urlDec(str) {
		str = str.replace(/\+/g,' ');
		return str.replace(/(%[0-9a-f]{2})+/ig,function(str){
			try {
				return decodeURIComponent(str);
			} catch(e) {
				return unescape(str);
			}
		});
	}
	
})(jQuery,this);

