StateEngine = Class.create();
StateEngine._instance = null;
StateEngine.goTo = function(key, value){
	StateEngine._instance.goTo(key, value);
};
StateEngine.setInnerFrame = function(iFrameId){
	StateEngine._instance.setInnerFrame(iFrameId);
}
StateEngine.registerOnNavigateListener = function(func){
	StateEngine._instance.registerOnNavigateListener(func);
}
StateEngine.hasState = function(){
	return StateEngine._instance.hasState();
}
StateEngine.getCurrentState = function(){
	return StateEngine._instance.getCurrentState();
}
StateEngine.prototype = {
	_form: null,
	_iframe: null,
	_loopPointer: 0,
	_currentAnchor: "",
	_isIE: false,
	_isAfterGoToCall: false,
	_navigateListeners: null,
	initialize: function(){
		this._isIE = ((window.navigator.userAgent.indexOf("MSIE") > 0) && (window.navigator.userAgent.indexOf("Opera") < 0));
		this._navigateListeners = [];
		Event.observe(window, 'load', this._onLoad.bindAsEventListener(this));
		Event.observe(window, 'unload', this._dispose.bindAsEventListener(this));
	},
	setInnerFrame: function(iFrameId){
		this._iframe = $(iFrameId)
	},
	goTo: function(value){
		if(this._isIE){
			this._iframe.contentWindow.location.search = value;
		}else{
			window.location.hash = value;
		}
		this._isAfterGoToCall = true;
	},
	registerOnNavigateListener: function(func){
		this._navigateListeners.push(func);
	},
	hasState: function(){
		var state = this.getCurrentState();
		return (state != null && state != '');
	},
	getCurrentState: function(){
		var anchor = (this._isIE)?this._iframe.contentWindow.location.search:window.location.hash;
		if(anchor.indexOf('?') == 0 || anchor.indexOf('#') == 0) anchor = anchor.substring(1);
		return anchor;
	},
	_dispose: function(){
		if (this._loopPointer) {
            window.clearTimeout(this._loopPointer);
            this._loopPointer = 0;
            this._iframe = null;
        }
	},
	_onLoad: function(){	
		this._loopPointer = window.setTimeout(this._onCurrentLoop.bind(this), 100);
	},
	_onCurrentLoop: function(){
		this._loopPointer = 0;
		if(this._iframe != null && this._currentAnchor != this.getCurrentState()){
			if(!this._isAfterGoToCall){
				this._onNavigate(this._currentAnchor);
			}else{
				this._isAfterGoToCall = false;
			}
			this._currentAnchor = this.getCurrentState();
		}
		this._loopPointer = window.setTimeout(this._onCurrentLoop.bind(this), 100);
	},
	_onNavigate: function(oldAnchor){
		for(var i = 0; i < this._navigateListeners.length; i++)
			this._navigateListeners[i](this.getCurrentState());
	},
	_getUrlWithoutAnchor: function(url){
		url = (!!url)?url:window.location.href;
		var index = url.indexOf('#');
		if(index < 0) return url;
		return url.substr(0,index);
	},
	_getHash: function(number){
		var hash = (new Date()).getTime(); hash += (hash << 10); hash ^= (hash >> 6); hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15);
		return Math.abs(hash);
	}
}
if(StateEngine._instance == null){
	StateEngine._instance = new StateEngine();
}