/**
 * HistoryManager
 * 
 * Observes back/forward button usage and saves states
 * for registered modules into the hash. This allows to
 * bookmark specific states for an application.
 * 
 * @version        1.0rc2 PORTED to MooTools 1.2
 * 
 * @see            Events, Options
 * 
 * @license        MIT License
 * @author        Harald Kirschner <mail [at] digitarald.de>
 * @copyright    2007 Author
 */
var HistoryManager=new Class({Implements:[Options,Events],options:{observeDelay:100,stateSeparator:";",iframeSrc:"/blank.jsp",onStart:$empty,onRegister:$empty,onUnregister:$empty,onStart:$empty,onUpdate:$empty,onStateChange:$empty,onObserverChange:$empty},dataOptions:{skipDefaultMatch:true,defaults:[],regexpParams:""},initialize:function(A){if(this.modules){return this}this.setOptions(A);this.modules=$H({});this.count=history.length;this.states=[];this.states[this.count]=this.getHash();this.state=null;return this},start:function(){this.observe.periodical(this.options.observeDelay,this);this.started=true;this.observe();this.update();this.fireEvent("onStart",[this.state]);return this},register:function(B,G,C,F,E,A){if(!this.modules){this.initialize()}var D=$merge(this.dataOptions,A||{},{defaults:G,onMatch:C,onGenerate:F,regexp:E});D.regexp=D.regexp||B+"-([\\w_-]*)";if(typeof D.regexp=="string"){D.regexp=new RegExp(D.regexp,D.regexpParams)}D.onGenerate=D.onGenerate||function(H){return B+"-"+H[0]};D.values=$A(D.defaults);this.modules.set(B,D);this.fireEvent("onUnregister",[B,D]);return{setValues:function(H){return this.setValues(B,H)}.bind(this),setValue:function(H,I){return this.setValue(B,H,I)}.bind(this),generate:function(H){return this.generate(B,H)}.bind(this),unregister:function(){return this.unregister(B)}.bind(this)}},unregister:function(A){this.fireEvent("onRegister",[A]);this.modules.remove(A)},setValues:function(B,A){var C=this.modules.get(B);if(!C||C.values.isSimilar(A)){return this}C.values=A;this.update();return this},setValue:function(B,A,D){var C=this.modules.get(B);if(!C||C.values[A]==D){return this}C.values[A]=D;this.update();return this},generate:function(B,A){var D=this.modules.get(B);var E=$A(D.values);D.values=A;var C=this.generateState();D.values=E;return"#"+C},observe:function(){if(this.timeout){return }var A=this.getState();if(this.state==A){return }if((Browser.Engine.trident||Browser.Engine.webkit419)&&(this.state!==null)){this.setState(A,true)}else{this.state=A}this.modules.each(function(D,B){var C=A.match(D.regexp);if(C){C.splice(0,1);C.complement(D.defaults);if(!C.isSimilar(D.defaults)){D.values=C}}else{D.values=$A(D.defaults)}D.onMatch(D.values,D.defaults)});this.fireEvent("onStateChange",[A]).fireEvent("onObserverChange",[A])},generateState:function(){var A=[];this.modules.each(function(C,B){if(C.skipDefaultMatch&&C.values.isSimilar(C.defaults)){return }A.push(C.onGenerate(C.values))});return A.join(this.options.stateSeparator)},update:function(){if(!this.started){return this}var A=this.generateState();if((!this.state&&!A)||(this.state==A)){return this}this.setState(A);this.fireEvent("onStateChange",[A]).fireEvent("onUpdate",[A]);return this},observeTimeout:function(){if(this.timeout){this.timeout=$clear(this.timeout)}else{this.timeout=this.observeTimeout.delay(200,this)}},getHash:function(){var A=top.location.href;var B=A.indexOf("#")+1;return(B)?A.substr(B):""},getState:function(){var B=this.getHash();if(this.iframe){var C=this.iframe.contentWindow.document;if(C&&C.body.id=="state"){var A=C.body.innerText;if(this.state==B){return A}this.istateOld=true}else{return this.istate}}if(Browser.Engine.webkit419&&history.length!=this.count){this.count=history.length;return $pick(this.states[this.count-1],B)}return B},setState:function(B,A){B=$pick(B,"");if(Browser.Engine.webkit419){if(!this.form){this.form=new Element("form",{method:"get"}).injectInside(document.body)}this.count=history.length;this.states[this.count]=B;this.observeTimeout();this.form.setProperty("action","#"+B).submit()}else{top.location.hash=B||"#"}if(Browser.Engine.trident&&(!A||this.istateOld)){if(!this.iframe){this.iframe=new Element("iframe",{src:this.options.iframeSrc,styles:{visibility:"hidden"}}).injectInside(document.body);this.istate=this.state}try{var D=this.iframe.contentWindow.document;D.open();D.write('<html><body id="state">'+B+"</body></html>");D.close();this.istateOld=false}catch(C){}}this.state=B},extend:$extend});Array=Array.implement({isSimilar:function(A){return(this.toString()==A.toString())},complement:function(C){for(var B=0,A=this.length;B<A;B++){this[B]=$pick(this[B],C[B]||null)}return this}});