var HistoryManager=new Class({Extends:HashListener,options:{delimiter:''},state:new Hash({}),stateCache:new Hash({}),fromHash:false,fromHandle:false,initialize:function(options){this.parent(options);this.addEvent('hashChanged',this.updateState.bind(this));},updateState:function(hash){var $this=this;if(this.options.delimiter)hash=hash.substr(this.options.delimiter.length);hash=new Hash(JSON.decode(decodeURIComponent(hash)));this.state.each(function(value,key){var nvalue,comperable,h_type;if(!hash.has(key)){nvalue=$this.state.get(key);$this.fireEvent(key+'-removed',[nvalue]);$this.state.erase(key);$this.stateCache.erase(key);hash.erase(key);return;}
h_type=$type(hash[key]);comperable=(h_type=='string'||h_type=='number'||h_type=='boolean')?hash[key]:JSON.encode(hash[key]);if(comperable!=$this.stateCache[key]){nvalue=hash.get(key);$this.state.set(key,nvalue);$this.stateCache.set(key,comperable);$this.fireEvent(key+'-updated',[nvalue]);$this.fireEvent(key+'-changed',[nvalue]);}
hash.erase(key);});hash.each(function(value,key){$this.state.set(key,value);v_type=$type(hash[key]);$this.stateCache.set(key,(v_type=='string'||v_type=='number'||v_type=='boolean')?value:JSON.encode(value));$this.fireEvent(key+'-added',[value]);$this.fireEvent(key+'-changed',[value]);});},set:function(key,value){var newState=new Hash(this.state);newState.set(key,value);this.updateHash(this.options.delimiter+newState.toJSON());return this;},remove:function(key){var newState=new Hash(this.state);newState.erase(key);this.updateHash(this.options.delimiter+newState.toJSON());return this;}});
