/*
 * 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;
            }

            /*
            if (this._curHash.length > 1) 
            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 (location.hash.indexOf('#') >= 0) {
                            $.history._callback(location.hash.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(/^#/, ''));
                }
            }
        },

        isKonqueror: function() {
            return /KHTML|Konqueror/.test(navigator.userAgent);
        },

        register: function(hash) {
            //remove all hash if any
            hash = hash.replace(/^#+/, '');

            var newhash;

            if ($.browser.safari) {
                newhash = hash;
            } else {
                newhash = (this.isKonqueror() ? '' : '#') + 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;

            }
            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);

                // 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;
            }
        }
    });

    $(document).ready(function() {
        $.history = new History(); // singleton instance
    });

})(jQuery);

