/*
 * jQuery history plugin
 *
 * Copyright (c) 2006 Taku Sano (Mikage Sawatari)
 * Licensed under the MIT License:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Modified by Lincoln Cooper to add Safari support and only call the callback once during initialization
 * for msie when no initial hash supplied.
 * API rewrite by Lauris Buk�is-Haberkorns
 */

(function($) {

function History()
{
    this._curHash = '';
    this._callback = function(hash){};
};

$.extend(History.prototype, {

    init: function(callback) {
        this._callback = callback;
        this._curHash = location.hash;

        if($.browser.msie) {
            // To stop the callback firing twice during initilization if no hash present
            if (this._curHash == '') {
                this._curHash = '#';
            }

            // add hidden iframe for IE
            $("body").prepend('<iframe id="jQuery_history" style="display: none;"></iframe>');
            var iframe = $("#jQuery_history")[0].contentWindow.document;
            iframe.open();
            iframe.close();
            iframe.location.hash = this._curHash;
        }
        else if ($.browser.safari) {
            // etablish back/forward stacks
            this._historyBackStack = [];
            this._historyBackStack.length = history.length;
            this._historyForwardStack = [];
            this._isFirst = true;
            this._dontCheck = false;
        }
        this._callback(this._curHash.replace(/^#/, ''));
        setInterval(this._check, 100);
    },

    add: function(hash) {
        // This makes the looping function do something
        this._historyBackStack.push(hash);
        
        this._historyForwardStack.length = 0; // clear forwardStack (true click occured)
        this._isFirst = true;
    },
    
    _check: function() {
        if($.browser.msie) {
            // On IE, check for location.hash of iframe
            var ihistory = $("#jQuery_history")[0];
            var iframe = ihistory.contentDocument || ihistory.contentWindow.document;
            var current_hash = iframe.location.hash;
            if(current_hash != $.history._curHash) {
            
                location.hash = current_hash;
                $.history._curHash = current_hash;
                $.history._callback(current_hash.replace(/^#/, ''));
                
            }
        } else if ($.browser.safari) {
            if (!$.history._dontCheck) {
                var historyDelta = history.length - $.history._historyBackStack.length;
                
                if (historyDelta) { // back or forward button has been pushed
                    $.history._isFirst = false;
                    if (historyDelta < 0) { // back button has been pushed
                        // move items to forward stack
                        for (var i = 0; i < Math.abs(historyDelta); i++) $.history._historyForwardStack.unshift($.history._historyBackStack.pop());
                    } else { // forward button has been pushed
                        // move items to back stack
                        for (var i = 0; i < historyDelta; i++) $.history._historyBackStack.push($.history._historyForwardStack.shift());
                    }
                    var cachedHash = $.history._historyBackStack[$.history._historyBackStack.length - 1];
                    if (cachedHash != undefined) {
                        $.history._curHash = location.hash;
                        $.history._callback(cachedHash);
                    }
                } else if ($.history._historyBackStack[$.history._historyBackStack.length - 1] == undefined && !$.history._isFirst) {
                    // back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
                    // document.URL doesn't change in Safari
                    if (document.URL.indexOf('#') >= 0) {
                        $.history._callback(document.URL.split('#')[1]);
                    } else {
                        $.history._callback('');
                    }
                    $.history._isFirst = true;
                }
            }
        } else {
            // otherwise, check for location.hash
            var current_hash = location.hash;
            if(current_hash != $.history._curHash) {
                $.history._curHash = current_hash;
                $.history._callback(current_hash.replace(/^#/, ''));
            }
        }
    },

    load: function(hash) {
        var newhash;
        
        if ($.browser.safari) {
            newhash = hash;
        } else {
            newhash = '#' + hash;
            location.hash = newhash;
        }
        this._curHash = newhash;
        
        if ($.browser.msie) {
            var ihistory = $("#jQuery_history")[0]; // TODO: need contentDocument?
            var iframe = ihistory.contentWindow.document;
            iframe.open();
            iframe.close();
            iframe.location.hash = newhash;
            this._callback(hash);
        }
        else if ($.browser.safari) {
            this._dontCheck = true;
            // Manually keep track of the history values for Safari
            this.add(hash);
            
            // Wait a while before allowing checking so that Safari has time to update the "history" object
            // correctly (otherwise the check loop would detect a false change in hash).
            var fn = function() {$.history._dontCheck = false;};
            window.setTimeout(fn, 200);
            this._callback(hash);
            // N.B. "location.hash=" must be the last line of code for Safari as execution stops afterwards.
            //      By explicitly using the "location.hash" command (instead of using a variable set to "location.hash") the
            //      URL in the browser and the "history" object are both updated correctly.
            location.hash = newhash;
        }
        else {
          this._callback(hash);
        }
    }
});

$(document).ready(function() {
    $.history = new History(); // singleton instance
});

})(jQuery);
