$(document).ready(function() {

    function load(url, incoming_direction, outgoing_direction, callback) {

        $.get(url, function(data) { 

            // Setup the content changes
            $(".content").addClass("hide-me");
            $("#viewing-window").append($(data).find(".content").hide().addClass("show-me"));

            // Animate the content transition
            $(".hide-me").hide("slide", { direction : outgoing_direction }, 500, function() {
                $(this).remove();
                $(".show-me").show("slide", { direction : incoming_direction }, 500).removeClass("show-me");
            });

            var data_object = $(data);

            // Animate the navigation transition
            // 1. create a super set of both navigation menus
            // 2. set animation styles
            // 3. swap the content
            // 4. animate the transition

            var old_nav = $("#breadcrumbs ul").children();
            var new_nav = data_object.find("#breadcrumbs ul").children();
            var super_nav = $("<ul></ul>");

            for (var i=0; i < Math.max(old_nav.length, new_nav.length); i++) {

                // if we have new and old li's
                if (i < old_nav.length && i < new_nav.length) {

                    var old_li = $(old_nav[i]);
                    var new_li = $(new_nav[i]);

                    var old_li_html = old_li.html();
                    var new_li_html = new_li.html();

                    // if exactly the same, push unchanged li
                    if (old_li_html == new_li_html) {
                        super_nav.append(new_li);
                    } 

                    // if replacing one current with another
                    else if (old_li.hasClass("current") && new_li.hasClass("current")) {
                        super_nav.append(old_li.addClass("nav-hide-me"));
                        if (i == 0)
                            super_nav.append(new_li.hide().css({fontSize: "100%", paddingLeft: "0px", opacity: "0"}).addClass("nav-show-me-grow-fade-first"));
                        else
                            super_nav.append(new_li.hide().css({fontSize: "100%", paddingLeft: "0px", opacity: "0"}).addClass("nav-show-me-grow-fade"));
                    }

                    // if replacing current with link (assuming same text)
                    else if (old_li.hasClass("current")) {
                        if (i == 0)
                            super_nav.append(new_li.css({fontSize: "140%"}).addClass("nav-shrink-me-first"));
                        else 
                            super_nav.append(new_li.css({fontSize: "140%", paddingLeft: "10px"}).addClass("nav-shrink-me"));
                    }

                    // if replacing link with current (assuming same text)
                    else if (new_li.hasClass("current")) {
                        if (i == 0)
                            super_nav.append(new_li.css({fontSize: "100%", paddingLeft: "0px"}).addClass("nav-grow-me-first"));
                        else
                            super_nav.append(new_li.css({fontSize: "100%", paddingLeft: "0px"}).addClass("nav-grow-me"));
                    }

                    // i don't know what the difference is
                    else {
                        super_nav.append(new_li);
                    }
                }
                // if just old
                else if (i < old_nav.length) {
                    super_nav.append($(old_nav[i]).css({fontSize: "140%"}).addClass("nav-hide-me")); // could be just fade
                }
                // if just new
                else if (i < new_nav.length) {
                    var new_li = $(new_nav[i]);
                    if (new_li.hasClass("current")) {
                        if (i == 0)
                            super_nav.append(new_li.hide().css({fontSize: "100%", paddingLeft: "0px", opacity: "0"}).addClass("nav-show-me-grow-fade-first"));
                        else 
                            super_nav.append(new_li.hide().css({fontSize: "100%", paddingLeft: "0px", opacity: "0"}).addClass("nav-show-me-grow-fade"));
                    }
                    else
                        super_nav.append(new_li.hide().css({opacity: "0"}).addClass("nav-show-me-fade"));
                }
            }

            $("#breadcrumbs").empty().append(super_nav);

            var hide_time = 50;
            var show_time = 100;

            $(".nav-hide-me").animate({fontSize: "100%", paddingLeft: "0px", opacity: "0"},hide_time,function() {
                $(this).remove();
            });
            $(".nav-shrink-me").animate({fontSize: "100%", paddingLeft: "0px"},hide_time).removeClass("nav-shrink-me");
            $(".nav-shrink-me-first").animate({fontSize: "100%", paddingLeft: "0px"},hide_time).removeClass("nav-shrink-me-first");
            $(".nav-grow-me").delay(hide_time).animate({fontSize: "140%", paddingLeft: "10px"},show_time).removeClass("nav-grow-me");
            $(".nav-grow-me-first").delay(hide_time).animate({fontSize: "140%"},show_time).removeClass("nav-grow-me-first");
            $(".nav-show-me-fade").delay(hide_time).show().animate({opacity: "1"},show_time).removeClass("nav-show-me-fade");
            $(".nav-show-me-grow-fade").delay(hide_time).show().animate({fontSize: "140%", paddingLeft: "10px", opacity: "1"},show_time).removeClass("nav-show-me-grow-fade");
            $(".nav-show-me-grow-fade-first").delay(hide_time).show().animate({fontSize: "140%", opacity: "1"},show_time).removeClass("nav-show-me-grow-fade-first");

            // Simply swap other elements
            $("#next").remove();
            $("#navigation").append(data_object.find("#next"));
            $("#prev").remove();
            $("#navigation").append(data_object.find("#prev"));
            $("#progress-bar").remove();
            $("#navigation").append(data_object.find("#progress-bar"));
            $("#edit_link").remove();
            $("#navigation").append(data_object.find("#edit_link"));
            $("#top").html(data_object.find("#github_link"));
            $("#banner_wrapper").html(data_object.find("#banner_wrapper").html());
            $("#nav_children").html(data_object.find("#nav_children").html());
            document.title = data_object.find("title").html();

            // Prettify the code!
            prettyPrint();
            
            if (callback) { callback(); }
        });
    }

    $("body").delegate("a", "click", function(event) {

        if ($(this).hasClass("ajax")) {

            event.preventDefault();

            // Which direction should new content come from?
            var outgoing_direction = "up";
            var incoming_direction = "down";
            if ($(this).hasClass("above")) {
                outgoing_direction = "down";
                incoming_direction = "up";
            } else if ($(this).hasClass("left")) {
                outgoing_direction = "right";
                incoming_direction = "left";
            } else if ($(this).hasClass("right")) {
                outgoing_direction = "left";
                incoming_direction = "right";
            }

            var link = $(this).attr("href");

            load(link, incoming_direction, outgoing_direction, function() {
                try {
                    history.pushState({ url: link, incomingDirection: incoming_direction, outgoingDirection: outgoing_direction }, "", link);
                } catch (error) {
                    // do nothing
                }
            });

        }

    });

    window.onpopstate = function(e) { 
        if (e.state && e.state.url) {
            load(e.state.url, e.state.outgoingDirection, e.state.incomingDirection);
        } else {
            load("/", "left", "right");
        }
    };

});

