var backButton = {
	event: { hash: '', refer: '', type: 'load' },
	copyHistory: [],
	addEvent: function(type,fn){
		if(type == 'backbutton' && (!this.events || !this.events.backbutton))
				this.addEvent('domready',backButton.start.bind(backButton));
		return this._addEvent(type,fn);
	},
	getHash: function() {
		return location.hash.substring(1);
	},
	start: function() {
		window.hash = this.hash.bind(this);
    if(window.ie) this.onHash = this.onIframe;
    if(window.khtml) {
      this.history = $A(history).slice(1);
      this.history.push(this.getHash());
      this.oldHistoryLength = location.hash ? -1 : history.length;
      this.onHash = this.onLink;
    }
		this.timer = this.onHash.pass(false,this).periodical(100);
	},
	onHash: function(force) {
	  var hash = this.getHash();
	  if(hash != this.event.hash || force) this.fireEvent(hash);
	},
	onLink: function(force) {
		var h = history.length;
    if (h != this.oldHistoryLength || force) {
       if(typeof (this.history[h-1]) == 'undefined') this.history = this.copyHistory.copy();
       this.fireEvent(this.history[h-1]);
       this.oldHistoryLength = h;
    }
	},
	onIframe: function() {
	  $clear(this.timer);
    this.iframe = new Element('iframe').setStyle('display','none').injectInside(document.body).contentWindow.document;
    if(this.getHash()) this.updateIFrame(this.getHash());
	},
	updateIFrame: function(hash) {
    this.iframe.open();
    this.iframe.write('<script>parent.location.hash = "'+hash+'"; parent.backButton.fireEvent("'+hash +'");</script>');
    this.iframe.close();
  },
	hash: function(hash) {
		if($type(hash) != 'string') return this.event.hash;
	  this.event.type = 'click';
    if(!window.ie) {
			if(window.khtml) {
      	var link = new Element('a').setProperty('href','#'+hash), event = document.createEvent('MouseEvents');
      	event.initEvent('click', true, true);
      	link.dispatchEvent(event);
      	if(this.history.length >= history.length) {
        	this.copyHistory = this.history.copy();
        	this.history = this.history.splice(0, history.length-1);
      	}
      	this.history.push(hash);
			} else location.hash = hash || '#';
			this.onHash(true);
    } else this.updateIFrame(hash);
	},
	fireEvent: function(hash) {
    this.event.hash = hash;
		Element.prototype.fireEvent.call(window, 'backbutton', [Object.extend({},this.event)]);
		Object.extend(this.event,{ refer: hash, type: 'backbutton' });
	}
};

window.extend({
	_addEvent: window.addEvent,
	addEvent: backButton.addEvent,
	hash: Class.empty
});