var JHistory = new Class({
  Implements : [Events,Options],
  operator : {},//functions to handle state data : Object {scope,function}
  options:{
    observerRate:500,
    delim:"&",
    assign:"=",
    restoreOnLoad:true,
    restoredInit:false,
    script:null // location of serverside script to recieve navigation history
  },
  initialize : function(options){
    this.setOptions(options);
    //set State from URL
    //if(location.hash && this.options.restoreOnLoad)window.addEvent('load',this.restore.bind(this));
    // set up observer
    this.current = location.hash;
    this.observer = window.setInterval(this.observe.bind(this),this.options.observerRate);
    this.pageTitle = document.title;
  },
  register:function(key,callback,defaultvalue){
//    console.log("registered -> "+key);
    key = key.trim();
    this.operator[key] = {callback:callback};
  },
  unregister:function(key){
    if(this.operator[key])delete this.operator[key];
  },
  restore:function(){
    var state = this.getState();
//    console.log(state);
    for(var key in state){
//      console.log(JSON.decode(state[key]));
      this.operator[key].value = state[key];
      this.operator[key].callback(JSON.decode(state[key]));
    }
    this.options.restoredInit = true;
  },
  change:function(key,value){
    if(this.options.restoreOnLoad){if(!this.options.restoredInit)return;}
    this.operator[key].value = JSON.encode(value);
    this.updateState();
  },
  updateState:function(){
    var hash='#';
    var key;
    var i=0;
    var title = document.title.split(" - ")[0];
    for(var key in this.operator){
      if(this.operator[key].value != undefined){
        if(i != 0) hash += this.options.delim;
        hash += key+this.options.assign+this.operator[key].value;
        title += " - "+key+":"+this.operator[key].value;
        i++;
      }
    }
    document.title = title;
    this.current = hash;
    location.hash = hash;
  },
  getState:function(){
    this.current = location.hash;
    var tmpArray = this.current.replace("#","").split(this.options.delim);
    var state = {};
    for(var i=0 ; tmpArray[i] ; i++){
      var prop = tmpArray[i].split(this.options.assign);
      state[prop[0]] = prop[1];
    }
    return state;
  },
  observe:function(){
    //console.log("DHTML_History.oberve");
    if(this.current == location.hash) return;
    this.restore();
  }
});
