
var g_oldDocumentHash;

jQuery.fn.slidingSubpages = function(optionalOptions){
    options = jQuery.extend(
        {
            timeout:        250,
            removeHeaders:  true,
            onchange:       undefined,
            headerTarget:   undefined
        },
        optionalOptions
    );
    
    panel = {};
    
    panel.jQuery = this.each(
        function() {
            var container = jQuery(this);
            
            var ids = [];
            
            container.children().each(
                function() {
                    var id = jQuery(this).attr('id');
                    
                    if (id && linkFor(id)) {
                        ids.push(id);
                    }
                }
            );

            var count = ids.length;

            if (count == 0) return;
            
            var defaultId = ids[0];
            
            function linkFor(id) {
                var obj = jQuery('a[href="#' + id + '"]');
                
                if (obj.size() == 0) return undefined;
                
                return obj;
            }

            function getActivePaneIndex(slidingPlane) {
                var curLeft = parseFloat(slidingPlane.css('left'));

                return Math.floor(-curLeft / slidingPlane.parent().outerWidth() + 0.5);
            }

            function makeActivePane(slidingPlane, id) {
                var linkForId = linkFor(id);
                
                if (linkForId) {                
                    var index = linkForId.attr('pane-index');
                
                    var curLeft = parseFloat(slidingPlane.css('left'));
                    var newLeft = -index * slidingPlane.parent().outerWidth();
                
                    var curHash = document.location.hash.toString();
                    var newHash = '#' + id;
                    
                    var oldPane = container.find('div[pane-id="' + ids[getActivePaneIndex(slidingPlane)] + '"]').parent();
                    var pane    = container.find('div[pane-id="' + id + '"]').parent();
                    
                    
                    // Set all panes max-height to the height of the active pane, so they don't add height:
                    container.find('div[sliding-subpage="true"]').css('height', pane.height());
										container.find('div[sliding-subpage="true"]').css('visibility', 'hidden');
                    pane.css('height', 'auto');
                    pane.css('visibility', 'visible');
                    if (newHash != curHash) {
                        if (id == defaultId && curHash.length <= 1) {
                            // Do nothing
                        }
                        else {
                            document.location.hash = newHash;
                            
                            // Track with Google Analytics, if installed:
                            if (pageTracker) {
                                pageTracker._trackPageview('/subpage-' + document.location.pathname.toString() + newHash);
                            }
                        }
                    }
                    
                    // Do the animation to select the current pane:
                    if (curLeft != newLeft) {
                        slidingPlane.animate(
                            {
                                left: newLeft + 'px'
                            },
                            options.timeout
                        );
                    }
                    
                    // Make sure the proper link is activated and do other stuff:
                    var listLink = jQuery('li a[href="#' + id + '"]');
                    
                    if (!listLink.hasClass('current')) {
                        jQuery('li a.current').removeClass('current');

                        listLink.addClass('current');
                    
                        if (options.onchange) options.onchange(id);
                    
                        if (options.headerTarget) {
                            var header = (options.headerTarget instanceof String) ? jQuery('#' + options.headerTarget) : options.headerTarget;
                            var html   = linkForId.attr('pane-header-html');
                            
                            if (html) {
                                header.html(html);
                            
                                if (truefontfamily) {
                                    header.each(
                                        function() {
                                            truefontfamily(this);
                                        }
                                    );                                
                                }
                            }
                        }
                    }
                }
            }
            
            function createClickActivator(slidingPlane) {
                return function() {
                    var paneId = jQuery(this).attr('pane-id');
                    
                    makeActivePane(slidingPlane, paneId);
                
                    return false;
                }
            }
            
            function rewriteFullLinksToRelativeLinks(ids) {                
                var url      = document.URL;
                var pageHash = /\/([^/]+)$/.exec(url)[1];
                var thisPage = /([^#]+)(#.*)?$/.exec(pageHash)[1];
                
                for (var index = 0; index < ids.length; index++) {
                    var id       = ids[index];
                    var relLink  = '#' + id;
                    var fullLink = thisPage + relLink;
                    
                    jQuery('a[href$="' + fullLink + '"]').each(
                        function() {
                            $(this).attr('href', relLink);
                        }
                    );
                }
            }
            
            rewriteFullLinksToRelativeLinks(ids);
            
            var containerWidth = container.outerWidth({margin:true});
            
            var slidingPlane = jQuery(document.createElement('div'));            
            
            slidingPlane.css('position', 'relative');
            slidingPlane.css('left', '0px');
            slidingPlane.width(containerWidth * count);
            
            panel.minIndex = 0;
            panel.maxIndex = count - 1;
            
            for (var i = 0; i < count; i++) {
                var id        = ids[i];
                var linkForId = linkFor(id);
                
                // Store the index and id inside the link:
                linkForId.attr('pane-index', i);
                linkForId.attr('pane-id',    id);
                
                linkForId.attr('pane-header-html', jQuery('li a[href="#' + id + '"]').html());
                
                var pane = jQuery(document.createElement('div'));
                
                pane.attr('sliding-subpage', 'true');
                
                // Each pane is floated left:
                pane.css('float',           'left');
                
                // Each pane will duplicate the padding and margin of the container:
                pane.css('padding-left',    container.css('padding-left'));
                pane.css('padding-right',   container.css('padding-right'));
                pane.css('padding-top',     container.css('padding-top'));
                pane.css('padding-bottom',  container.css('padding-bottom'));
                
                pane.css('margin-left',     container.css('margin-left'));
                pane.css('margin-right',    container.css('margin-right'));
                pane.css('margin-top',      container.css('margin-top'));
                pane.css('margin-bottom',   container.css('margin-bottom'));
                
                // Hide any overflow (this is needed for animating height of pane):
                pane.css('overflow',        'hidden');
                
                pane.width(container.width());
                pane.css('min-height', '1px');
                
                var content = jQuery(jQuery('#' + id).get(0));
                
                // Remove the headers, if specified:
                content.children().eq(0).each(
                    function() {
                        if (/h\d+/i.test(this.tagName)) {
                            if (options.removeHeaders) {
                                $(this).css('display', 'none');
                            }
                        }
                    }
                )
                
                // Remove the content from its existing location and put it into the pane:
                content.remove();
                
                // Store 'id' in 'pane-id' so client has a way of looking up content:
                content.attr('pane-id', id);
                
                // Remove the 'id' attribute (which forces the browser to scroll the container if URL has hash location):
                content.removeAttr('id');
                
                // Add the content to the pane:
                content.appendTo(pane);
                
                // Add the pane to the sliding plane:
                slidingPlane.append(pane);
                
                // Deal with clicking on the links:
                linkForId.click(createClickActivator(slidingPlane));
            }
            
            container.scrollTop(0);
            container.scrollLeft(0);
            container.css('margin',   0);
            container.css('padding',  0);
            container.css('overflow', 'hidden');
            container.width(containerWidth);
            container.prepend(slidingPlane);

            // Install helper functions in panel so that client can manipulate the sliding plane:
            panel.idToIndex = function(id) {
                var linkForId = linkFor(id);
                
                if (!linkForId) return undefined;
                
                return linkForId.attr('pane-index');
            }
            
            panel.indexToId = function(index) {
                var result = jQuery('li a[pane-index="' + index + '"]');
                
                var paneId = result.attr('pane-id');
                
                return paneId;
            }

            panel.moveToId = function(id) {
                makeActivePane(slidingPlane, id);

                return true;
            }

            panel.moveToIndex = function(index) {
                makeActivePane(slidingPlane, panel.indexToId(index));

                return true;
            }
            
            panel.moveLeft = function() {
                var index = getActivePaneIndex(slidingPlane);
                
                if (index == panel.minIndex) return false;
            
                panel.moveToIndex(index - 1);
                
                return true;
            }
            
            panel.moveRight = function() {
                var index = getActivePaneIndex(slidingPlane);
                
                if (index == panel.maxIndex) return false;
                
                panel.moveToIndex(index + 1);
                
                return true;
            }
            
            panel.moveToStart = function() {
                return moveToIndex(panel.minIndex);
            }
            
            panel.moveToEnd = function() {
                return moveToIndex(panel.maxIndex);
            }
            
            //Now look at the document URL to see if some subsection is selected.
            if (document.location.hash && document.location.hash.toString().length > 1) {
                var selectedId = document.location.hash.toString().substring(1);
                
                makeActivePane(slidingPlane, selectedId);
                
                jQuery('html,body').scrollTop(0);
            }
            else {
                // First pane will be visible, make it active:
                makeActivePane(slidingPlane, ids[0]);
            }
            
            g_oldDocumentHash = document.location.hash.toString();
            
            setInterval(
                function() {
                    var hash = document.location.hash.toString();
                    
                    if (g_oldDocumentHash != hash) {
                        var idToActivate;
                        
                        if (hash.length > 1) {
                            idToActivate = hash.substring(1);
                        }
                        else {
                            idToActivate = defaultId;
                        }
                        
                        g_oldDocumentHash = hash;
                        
                        makeActivePane(slidingPlane, idToActivate);
                    }
                },
                100
            )
        }
    );
    
    return panel;
}