/* --------------------------------------------------------------------------------------
 * history.js
 * version 2.00
 * @20110324
 * Required common.js ver1.40 later
-------------------------------------------------------------------------------------- */

VCOMN.History = function (callback) {
  this.initialize.apply(this, arguments);
}
VCOMN.History.prototype = {
  initialize :function (callback) {
    if (typeof VCOMN._historyWork == 'undefined') {
      VCOMN._historyWork = new VCOMN.HistoryWork();
    }
    VCOMN._historyWork.addCallback(callback);
  },
  setHistory: function (hash, isCallback) {
    VCOMN._historyWork.setHistory(hash, isCallback);
  },
  getHistory: function () {
    return VCOMN._historyWork.getHistory();
  }
};

VCOMN.HistoryWork = function () {
  this.initialize.apply(this, arguments);
}

VCOMN.HistoryWork.prototype = {
  initialize :function () {
    this.callbacks = [];
    this.currentHash = location.hash;
    this.useIframe = VCOMN.env.isIE && parseInt(VCOMN.env.version) < 8;
    if (this.useIframe) {
      if (this.currentHash == '') {
        this.currentHash = '#';
      }
      var elem = document.createElement('div');
      this.iframe = document.createElement('iframe');
      this.iframe.id = 'history_iframe';
      this.iframe.style.display = 'none';
      elem.appendChild(this.iframe);
      document.body.insertBefore(elem.firstChild, document.body.firstChild);
      this._updateIframeHash(this.currentHash);
    } else if (VCOMN.env.isSafari) {
      this.webKitHistoryBack = [];
      this.webKitHistoryBack.length = history.length;
      this.webKitHistoryFoward = [];
      this.isWebKitFirst = true;
    }
    setInterval(VCOMN.bindFunc(this._checkHistory, this), 100);
  },
  addCallback: function (callback) {
    this.callbacks.push(callback);
  },
  setHistory: function (hash, isCallback) {
    var newhash = hash;
    if (!VCOMN.env.isSafari) {
      newhash = '#' + hash;
      location.hash = newhash;
    }
    this.currentHash = newhash;
    if (this.useIframe) {
      this._updateIframeHash(this.currentHash);
    } else if (VCOMN.env.isSafari) {
      this.webKitDontCheck = true;
      this.webKitHistoryBack.push(hash);
      this.webKitHistoryFoward.length = 0;
      this.isWebKitFirst = true;
      var fn = function() {this.webKitDontCheck = false;};
      window.setTimeout(VCOMN.bindFunc(fn, this), 200);
    }
    if (isCallback) {
      this._callback(this.currentHash.replace(/^#/, ''));
    }
    if (VCOMN.env.isSafari) {
      location.hash = newhash;
    }
  },
  getHistory: function () {
    this._checkHistory();
    return this.currentHash.replace(/^#/, '');
  },
  _updateIframeHash: function (value) {
    var iframe = this.iframe.contentWindow.document;
    iframe.open();
    iframe.close();
    iframe.location.hash = value;
  },
  _checkHistory: function () {
    if (this.useIframe) {
      if (location.hash != this.currentHash && location.hash != '' && this.currentHash != '#') {
        this.setHistory(location.hash.replace(/^#/, ''), true);
        return;
      }
      if (!this.iframe) {
        return;
      }
      var iframe = this.iframe.contentDocument || this.iframe.contentWindow.document;
      if (this.currentHash != iframe.location.hash) {
        var current_hash = iframe.location.hash;
        location.hash = current_hash;
        this.currentHash = current_hash;
        this._callback(this.currentHash.replace(/^#/, ''));
      }
    } else if (VCOMN.env.isSafari) {
      if (!this.webKitDontCheck) {
        var historyDelta = history.length - this.webKitHistoryBack.length;
        if (historyDelta) {
          this.isWebKitFirst = false;
          if (historyDelta < 0) {
            for (var i = 0; i < Math.abs(historyDelta); i++) {
              this.webKitHistoryFoward.unshift(this.webKitHistoryBack.pop());
            }
          } else {
            for (var i = 0; i < historyDelta; i++) {
              this.webKitHistoryBack.push(this.webKitHistoryFoward.shift());
            }
          }
          var cachedHash = this.webKitHistoryBack[this.webKitHistoryBack.length - 1];
          if (cachedHash == undefined) {
            cachedHash = location.hash;
            cachedHash = cachedHash.replace(/^#/, '');
            this.webKitHistoryBack[this.webKitHistoryBack.length - 1] = cachedHash;
          }
          this.currentHash = cachedHash;
          this._callback(cachedHash);
        } else if (this.webKitHistoryBack[this.webKitHistoryBack.length - 1] == undefined && !this.isWebKitFirst) {
          var param = '';
          if (document.URL.indexOf('#') >= 0) {
            param = document.URL.split('#')[1];
          }
          this._callback(param);
          this.isWebKitFirst = true;
        }
      }
    } else {
      if (this.currentHash != location.hash) {
        this.currentHash = location.hash;
        this._callback(this.currentHash.replace(/^#/, ''));
      }
    }
  },
  _callback: function (param) {
    if (this.callbacks.length) {
      for (var i = 0; i < this.callbacks.length; i++) {
        this.callbacks[i](param);
      }
    }
  }
};

