


// track browsing history to enable back/forward browser navigation
HistoryManager.prototype = {

        
    // main page content loader
    loader: undefined,
    
    // secret iframe for history
    iframe: undefined,
    
    // main page content URL
    currentURL: null,
    
    
    // returns the first root loader in a non-ready state or null if all
    // root loaders are currently ready
    getNonReadyRootLoader: function() {
        for (var i = 0; i < ContentLoader.rootLoaders.length; i++) {
            if (!ContentLoader.rootLoaders[i].isReady()) {
                return ContentLoader.rootLoaders[i];
            }
        }
        return null;
    }, // getNonReadyRootLoader
    
    
    // restores earlier/future content in response to back/forward navigation
    restoreContent: function(pageURL, contentURL, itemPath, deselectList, time) {
        
        // check whether this history entry has been armed or if this is
        // simply the initial load of the history iframe
        var armed = true;        
        var cookie = "history-armed-" + time + "=";
        var index = document.cookie.indexOf(cookie);
        if (index != -1) {
            var semicolon = document.cookie.lastIndexOf(";", index);
            if (document.cookie.substring(semicolon + 1, index).trim() == "") {
                semicolon = document.cookie.indexOf(";", index + cookie.length);
                if (semicolon == -1) {
                    semicolon = document.cookie.length;
                }
                armed = document.cookie.substring(index + cookie.length, semicolon) != "false";
            }
        }
        if (!armed) {
            // arm this history entry in response to the initial iframe load
            document.cookie = cookie + "true; max-age=0";
            return;
        }
            
        if (pageURL != window.location) {
            
            // wrong page URL so ignore content and just reload the page
            window.location.replace(pageURL);
            
        } else if (contentURL != this.loader.getContentURL()) {
            
            // update notion of current content URL
            this.currentURL = contentURL;
            
            // update menu state
            var deselectIDs = deselectList.split(",");
            for (var i = 0; i < deselectIDs.length; i++) {
                var element = document.getElementById(deselectIDs[i]);
                if (element && element.shellMenu) {
                    element.shellMenu.deselectItem();
                }
            }
            ShellMenu.setItemPath(itemPath, false);
            
            // load content
            this.loader.loadURL(contentURL);
            
        }
    }, // restoreContent
    
    
    // responds to main page content arrival
    loadedContent: function(loader) {
        
        var contentURL = this.loader.getContentURL();
        
        if (contentURL != null && contentURL != this.currentURL) {
            
            var i;
            
            // check for quiescent root content loaders
            var nonReadyLoader = this.getNonReadyRootLoader();
            if (nonReadyLoader != null) {
                // one of the root content loaders is not ready
                if (nonReadyLoader !== this.loader) {
                    // try again when the unstable loader finishes up
                    var self = this;
                    var listener = new Object();
                    listener.loadedContent = function() {
                        nonReadyLoader.removeContentListener(listener);
                        self.loadedContent(nonReadyLoader);
                    };
                    nonReadyLoader.addContentListener(listener);
                }
                return;
            }
            
            // collect menu state
            var menuElements = DOMUtil.getElementsByClassName(document.body, "shell_menu");
            var menuIDs = [];
            for (i = 0; i < menuElements.length; i++) {
                if (menuElements[i].id) {
                    menuIDs.push(menuElements[i].id);
                }
            }
            var menu = document.getElementById("main").shellMenu;
            var itemPath = "top_nav:";
            var isFirstItem = true;
            while (menu && menu.selectedItem && menu.selectedItem.id) {
                if (!isFirstItem) {
                    itemPath += "/";
                }
                isFirstItem = false;
                itemPath += menu.selectedItem.id;
                for (i = 0; i < menuIDs.length && menuIDs[i] != menu.element.id; i++);
                if (i < menuIDs.length) {
                    menuIDs.splice(i, 1);
                }
                menu = menu.targetElement.shellMenu;
            }
            if (menu) {
                itemPath += ".";
            }
            
            if (!this.iframe) {
                // no iframe assigned, so look for one
                this.iframe = document.getElementById("history_iframe");
                if (!this.iframe) {
                    // create the iframe and attach it to the document
                    this.iframe = window.document.createElement("iframe");
                    this.iframe.id = "history_iframe";
                    this.iframe.style.display = "none";
                    window.document.body.appendChild(this.iframe);
                }
                // link the history manager to the secret iframe
                this.iframe.historyManager = this;
            }
            
            // set a cookie to prevent the history iframe from changing
            // content when it first loads
            var time = new Date().getTime();
            document.cookie = "history-armed-" + time + "=false";
            
            // update the secret history iframe to reflect the newly loaded page content
            this.iframe.src = "/history_iframe"
                                + "?pageURL=" + encodeURIComponent(window.location)
                                + "&contentURL=" + encodeURIComponent(contentURL)
                                + "&itemPath=" + encodeURIComponent(itemPath)
                                + "&deselectList=" + encodeURIComponent(menuIDs.join(","))
                                + "&time=" + encodeURIComponent(time);
            
            // keep track of the current main content URL
            this.currentURL = contentURL;
            
        }
                
    } // loadedContent
        
        
}; // HistoryManager.prototype


// creates a new browsing history manager
function HistoryManager() {
    
    // monitor and affect the main page content section
    this.loader = document.getElementById("page_content").contentLoader;
    this.loader.addContentListener(this);
    this.loadedContent();
    
} // HistoryManager


// prepare history manager when the page loads
EventHandling.executeOnLoad(function() {
    new HistoryManager();
});

