/* global $ */

/*===========================================================================*/
//
// This is the main JavaScript entry point of the jazzunique website
//

/*
If you want to keep the CSS :hover effect for when JavaScript is not available but remove it when it is available, you could add a class to the body element (or any other element that contains all the hovered items), then declare your :hover rules like this:

body.noJS img:hover { // apply CSS hover effect // }

Then, at the start of your JavaScript simply remove the 'noJS' class, which will disable the basic CSS :hover effect. Then apply the fancy hover effect as described by JohnRiv above.
*/

$.fn.reorder = function() {
    // http://blog.rebeccamurphey.com/2007/12/11/jquery-plugin-randomly-reorder-children-elements/

    // random array sort from
    // http://javascript.about.com/library/blsort2.htm
    function randOrd() { return(Math.round(Math.random())-0.5); }

    return($(this).each(function() {
        var $this = $(this);
        var $children = $this.children();
        var childCount = $children.length;
        if (childCount > 1) {
            $children.remove();
            var indices = new Array();
            for (i=0;i<childCount;i++) { indices[indices.length] = i; }
            indices = indices.sort(randOrd);
            $.each(indices,function(j,k) { $this.append($children.eq(k)); });
        }
    }));
}

$(document).ready(function() {

    jQuery.fn.extend({
        anchorOverlay: function(options) {
            function initOverlay($origAnchor) {
                if (options.speed === undefined) { options.speed = 250; }
                if (options.hoverOver === undefined) { options.hoverOver = function () { }; }
                if (options.hoverOut === undefined) { options.hoverOut = function () { }; }

                $origAnchor.wrap("<div>");
                $origAnchor.parent("div").addClass("ui-anchor-overlay-wrapper")
                                            .prepend("<a></a>");
                var $proxyAnchor = $origAnchor.parent("div").find("a").eq(0);
                $proxyAnchor.addClass("ui-anchor-overlay-proxy")
                            .addClass( $origAnchor.attr("class"))
                            .attr("href", $origAnchor.attr("href"))
                            .attr("title", $origAnchor.attr("title"))
                            .width( $origAnchor.width() )
                            .height( $origAnchor.height() )
                            .click( function() {
                                // Pass the click to the original link
                                $origAnchor.click();
                                return false;
                            })
                            .hover(options.hoverOver, options.hoverOut);
            }

            if ( $(this).length > 1 ) {
                $(this).each( function(i) {
                    // Wrap the anchor with a div
                    initOverlay( $(this) );
                });
            }
            else {
                initOverlay( $(this) );
            }
        },

        /* Adjusts *ALL* anchors in the page to use the ``pageLoaderClick``
           handler on ``click`` events. The handler is unbound first to
           prevent any doubled events.
         */
        ajaxifyAnchors: function(pageLoader) {

            function pageLoaderClick(event) {
                // Load the url through the PageLoader
                pageLoader.load( $(this).attr("href") );
                // Prevent default anchor behaviour
                return false;
            }

            function doAjaxifyAnchor($anchor) {
                $anchor
                    .unbind( "click", pageLoaderClick )
                    .bind( "click", pageLoaderClick );
            }

            if ( $(this).length > 1 ) {
                $(this).each( function(i) {
                    doAjaxifyAnchor( $(this) );
                });
            }
            else {
                doAjaxifyAnchor( $(this) );
            }


        }

    });

    // ------------------------------------------------------------------------
    // JazzuniqueSite class (singleton)
    // ------------------------------------------------------------------------
    function JazzuniqueSite() {
        var this_site = this;
        var hashCnt = 0;
        var $navOverlay = null;

        this.isIE6 = function() {
            if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10)===6 ) {
                return true;
            } else {
                return false;
            }
        };

        this.pageLoader = new PageLoader({
            pageUrl: document.location.href,
            pageLoaded: function(pageUrl, htmlData, pageClass, bodyClass) {
/*                console.log("Page loaded: url=" + pageUrl + ", pageClass="
                                                + pageClass + ", pageBodyClass=" + bodyClass);*/
                /* console.log( $("#page-permalink a").attr("href") );*/
                this_site.updateNavigation(pageUrl);

                if (pageClass === "pageclass-flatpage" || pageClass === "pageclass-listpage"
                    || pageClass === "pageclass-frontpage" || pageClass === "pageclass-archive") {

                    var $content = $(htmlData).find("#content");
                    $("#content").slideUp("normal", function() {
                        // Set the bodyclass of the page to the new page's class.
                        $("body").attr("class", bodyClass);

                        // Hide the to-be-inserted content
                        $content.hide();
                        // Replace the old with the new content
                        $(this).replaceWith( $content );
                        // and slide down the new content in place
                        if ( $("#content").text().length > 0 ) {
                            $("#content").slideDown("normal", function() {
                                // Class specific actions
                                if (pageClass === "pageclass-listpage") {
                                    this_site.initContentList();
                                    this_site.initContentListScroller();
                                    this_site.initImageListscroller();
                                    this_site.initListHover();
                                }
                                if (pageClass === "pageclass-archive") {
                                    this_site.initListHover();
                                    this_site.initArchiveContentList();
                                }
                                if (pageClass === "pageclass-frontpage") {
                                    this_site.initFrontpage();
                                }

                                // Page specific actions
                                this_site.initNewsletterForm();
                            });
                        }
                    });

                    this_site.updatePageTitle(htmlData);
                }

            }
        });

        // ----------------------- Priviliged functions ----------------------

        this.init = function() {

            this.initNavigation();
            this.initContentList();
            this.initContentListScroller();
            this.initImageListscroller();
            this.initListHover();
            this.initAjaxLoader();
            this.initFrontpage();
            this.initMembersDetailPage();

            this.updateNavigation(document.location.href);
            // Make the logo ajaxian
            //$("#header a").ajaxifyAnchors(this_site.pageLoader);
            $("#header a:not(.no-ajax)").ajaxifyAnchors(this_site.pageLoader);

            // $.ajaxHistory.initialize();

            // If the user starts directly with the archive page, we need to
            // initialize the archive content list explicitly
            if( $("body").hasClass("archivepage") ) {
                this_site.initArchiveContentList();
            }

            this.initNewsletterForm();

        };


        this.initNavigation = function () {

            var $nav = $("#nav");

            // Remove all .nojs class from the nav links to prevent
            // default CSS background coloring.
            $nav.find("a.nojs").removeClass("nojs");

            // Append an overlay <div> to the body. The overlay
            // will be displayed whenever an nav link is clicked and thereby
            // prevents that another link is clicked while loading.
            $("body").append("<div id='loader-overlay'></div>");
            this.$navOverlay = $("#loader-overlay");
            this.$navOverlay.width( $("body").outerWidth() )
                            .height( $("body").outerHeight() )
                            .css("position", "absolute")
                            .css("background-color", "#666")
                            .css("opacity", "0.0")
                            .css({top: 0, left: 0})
                            .css("z-index", "2000")
                            .hide();
            if (this.isIE6()) {
                this.$navOverlay.css("background", "url(/media/css/img/full_transparent_pixel.gif) repeat 0 0");
            }

            // If any of the first-level navigation items is clicked, toggle it
            // open or close.
            $("ul.level-1 > li > a").each(function() {
                var $secondLevelUl = $(this).parent("li").children("ul").eq(0);
                if ($secondLevelUl.children().length !== 0) {
                    $(this).toggle(
                        function() { $secondLevelUl.slideDown("fast"); },
                        function() { $secondLevelUl.slideUp("fast"); }
                    );
                }
            });

            // Initially slide up all second level entries
            $("ul.level-2").slideUp("normal");

            // Open the navigation path of the current item
            $("#nav a.nav-current").parents("ul.level-2").slideDown();

            // Replace the default behaviour of all navigation links with
            // some AJAX-specific one.
            // Exclude entries that have a css class "no-ajax".
            // FIXME: Link text has to be clicked directly, even though the
            //        a element is set to display block.
            $("#nav a:not(.no-ajax)").ajaxifyAnchors(this_site.pageLoader);

            // Show the permalink field
            $("#header #page-permalink").fadeIn()
                .find("a").click(function(){
                    var href = $(this).attr("href");
                    // Open the navigation to avoid to jumpy visual change
                    $("#nav ul.level-2").slideDown("normal", function() {
                        // Change to the url when permalink is clicked
                        document.location = href;
                    });
                });

            if (this.isIE6()) { /* do not use anchorOverlay with IE6 */ }
            else {
                $("#nav a").anchorOverlay({
                                    hoverOver: function (event) {
                                        $(event.target).css("background", "#DC0169")
                                                    .fadeTo(120, 0.5);
                                    },
                                    hoverOut: function (event) {
                                        $(event.target).fadeTo(120, 0.0);
                                    }
                                });
            }
        };

        /* Updates the navigation bar to reflect the location of the given
           ``permalink``.

         */
        this.updateNavigation = function(permalink) {
            this.updateNavigationCurrent(permalink);

            // Update the permalink
            $("#page-permalink a").attr("href", permalink);

        };

        this.updatePageTitle = function (htmlData) {
            // Update the page title. Unfortunately it is not possible
            // to select elements in the <head> of the returned data
            // using jQuery. So we have to use plain regex here.
            var pageTitleRe = /<title>(.*)<\/title>/;
            var pageTitleResult = pageTitleRe.exec(htmlData);

            if (pageTitleResult.length === 2) { document.title = pageTitleResult[1]; }
        };


        /* Searches the menu entry identified by the given ``permalink`` and
           makes it the selected entry.

           If the given ``permalink`` does not have a direct match in the
           navigation, the last component of the ``permalink`` is stripped
           away and the search is repeated. This procedure is called
           recursively until a match is found or the ``permalink`` was
           finally stripped to the root "/" url.
         */
        this.updateNavigationCurrent = function(permalink) {
            // Find the nav anchor that matches or starts with the given
            // permalink.
            var $anchor = $("#nav a[href=" + permalink + "]");

            if ($anchor.length === 1) {
                // console.log("Found exactly one match for '" + permalink + "'");
                $("#nav .nav-current").removeClass("nav-current");
                $anchor.addClass("nav-current")
                    .parents("ul").slideDown()
                        .prev("div").find("a").addClass("nav-current");
            }
            else if ($anchor.length === 0 && permalink !== "/") {
               // console.log("Found no match for '" + permalink + "'");
               // Strip the last component and try again
               var lastSlashIndex = permalink.lastIndexOf("/");
               if (lastSlashIndex === permalink.length-1) {
                    // Slash is the last character.. strip it and search again
                    lastSlashIndex = permalink.lastIndexOf("/", lastSlashIndex-1);
               }
               if (lastSlashIndex !== -1 ) {
                   var new_permalink = permalink.substring(0, lastSlashIndex+1);
                   this_site.updateNavigationCurrent(new_permalink);
               }
            }
            else if ($anchor.length >= 1) {
                // console.log("Found more than one match for '" + permalink + "'");
                // console.dir($anchor);
                var $filteredAnchors = $anchor.not(".ui-anchor-overlay-proxy");
                if ($filteredAnchors.length === 1) {
                    $("#nav .nav-current").removeClass("nav-current");
                    $filteredAnchors.addClass("nav-current")
                           .parents("ul").slideDown()
                                .prev("div").find("a").addClass("nav-current");

                }
                else {
                    // There really are two entries with the same URL!
                    // This only happens with first level entries which default
                    // to their first child... so make both current
                    $("#nav .nav-current").removeClass("nav-current");
                    $filteredAnchors.addClass("nav-current")
                           .parents("ul").slideDown()
                                .prev("div").find("a").addClass("nav-current");
                }
            }
        };


        this.initAjaxLoader = function() {

            $("#ajaxloader").ajaxStart(function(){
                this_site.$navOverlay
                    .width( $("body").width() )
                    .height( $("body").height() )
                    .show();
                $(this).fadeIn();
            });
            $("#ajaxloader").ajaxStop(function(){
                $(this).fadeOut();
                this_site.$navOverlay.hide();
            });
        };

        this.initContentListScroller = function() {
            if ( $("body").hasClass("frontpage") ) { return; }

            var height = 0;
            if ($("body").hasClass("newspage")) { height = 579;}
            else if ($("body").hasClass("archivepage")) { height = 489;}
            else { height = 501; }

            if ( $("body").hasClass("archivepage") ) {
                var itemCount = $("ul.contentlist li").length;
                if (itemCount > 24 ) {
                    $("ul.contentlist").jcarousel({
                        vertical: true,
                        scroll: 1,
                        animation: 300,
                        easing: "easeInOutQuart",
                        size: Math.ceil(itemCount/4),
                        buttonNextHTML: '<a ><span></span></a>',
                        buttonPrevHTML: '<a ><span></span></a>',
                        initCallback: function (carousel, state) {
                            carousel.container.css("height", "auto");
                            carousel.clip.css("height", "auto");
                            carousel.buttonPrev.hide().slideDown("fast");
                            carousel.buttonNext.hide().slideDown("fast");
                            carousel.clip.animate({height: height}, 400);
                            carousel.container.animate({height: height}, 400);
                            carousel.container.css("height", height);
                            carousel.clip.css("height", height);
                        }
                    });
                }
            }
            else {
                if ( $(".contentlist li").length > 6 ) {

                    $("ul.contentlist").jcarousel({
                        vertical: true,
                        scroll: 1,
                        animation: 300,
                        easing: "easeInOutQuart",
                        buttonNextHTML: '<a ><span></span></a>',
                        buttonPrevHTML: '<a ><span></span></a>',
                        initCallback: function (carousel, state) {
                            carousel.container.css("height", "auto");
                            carousel.clip.css("height", "auto");
                            carousel.buttonPrev.hide().slideDown("fast");
                            carousel.buttonNext.hide().slideDown("fast");
                            carousel.clip.animate({height: height}, 495);
                            carousel.container.animate({height: height}, 495);
                            carousel.container.css("height", height);
                            carousel.clip.css("height", height);

                            $("ul.contentlist").mousewheel(function(event, delta) {
                                if (delta > 0) {
                                    //console.log("up" + delta)
                                    carousel.prev();
                                    return false;
                                }
                                else if (delta < 0) {
                                    // $('#logger').append('#test1: down ('+delta+')<br />');
                                    carousel.next();
                                    return false;
                                }
                            });

                        }
                    });
                }
            }

        };

        this.initImageListscroller = function() {
            // Only show the scroll arrows if there are more than one
            // entries.
            if( $(".imagelist").length ) {
                var imageCount = parseInt($(".imagelist").attr("count"));
                $(".imagelist").find("li").show().end()
                    .jcarousel({
                        vertical: false,
                        scroll: 1,
                        size: imageCount,
                        animation: 350,
                        easing: "easeInOutQuart"/*,
                        itemLoadCallback:{
                            onBeforeAnimation: function(carousel, state) {
                                if (state==="init" || state === "next") {
                                    var slug = $(carousel.container).parents(".content").find(".slug").html();

                                    // If state is "init", reload the first image via AJAX - this
                                    // is necessary because otherwise IE6 fucks up the image loading.
                                    if (this_site.isIE6() && state==="init") {
                                        $.get("/contentimage/" + slug + "/0/",
                                            function(data) {
                                                carousel.add(1, data);
                                            }
                                        );
                                    }

                                    // Get the 1-based index
                                    var index = parseInt(carousel.first);

                                    // Check if the next <li> already has a loaded image
                                    //console.dir(carousel.container.prevObject);
//                                     alert("/contentimage/" + slug + "/" + index + "/");
                                    var $listItem = carousel.container.prevObject.find("li").eq(index);
                                    if ($listItem.find("img").length === 0) {
                                        $.get("/contentimage/" + slug + "/" + index + "/",
                                            function(data) {
                                                carousel.add(index+1, data);
                                            }
                                        );
                                    }
                                }
                            },
                            onAfterAnimation: {}
                        }*/
                    });
            }
        };

        this.initListHover = function() {
            if (this.isIE6()) {}
            else {
                $(".img-overlay").hover(
                    function() {
                        if (!$(this).parent("li").hasClass("current")) {
                            $(this).fadeTo("fast", 0.5);
                        }
                    },
                    function() {
                        if (!$(this).parent("li").hasClass("current")) {
                            $(this).fadeTo("fast", 0.0);
                        }
                    }
                );
            }
        };


        this.initContentList = function() {
            if ( $("body").hasClass("frontpage") ) { return; }

            // Select the first entry by default
            this_site.selectContentItem( $(".contentlist a").eq(0) );

            $(".contentlist a").click(function() {
                var slug = $(this).parents(".content").find(".slug").html();
                // update navigation. Only update the permalink - jazzunique
                // does not want to reflect the change in the nav menu
                // this_site.updateNavigation( $(this).attr("href") );
                $("#page-permalink a").attr("href", $(this).attr("href"));
                $.get( "/contentdetails/" + slug + "/",
                    function(data) {
                        $("#contentdetails-container").slideUp("normal",
                            function() {
                                var $data = $(data);
                                $data.hide();
                                $(this).replaceWith($data);

                                $data.slideDown("normal", function() {
                                    this_site.initImageListscroller();
                                });

                                var contentTitle = $data.find("h3").eq(0).html();
                                var newDocumentTitle = "JAZZUNIQUE - " + $("#content > h2").html().toUpperCase() + " - " +  contentTitle;
                                document.title = newDocumentTitle;
                            }
                        );
                    }
                );

                // Select the current item
                this_site.selectContentItem( $(this) );

                return false;
            });
        };

        this.selectContentItem = function($item) {
            // Select the current item
            $item.parents("ul").children("li").not($item.parents("li"))
                .removeClass("current")
                .find(".img-overlay").fadeTo("fast", 0.0);

            $item.parents("li").addClass("current");
        };

        this.initFrontpage = function() {
            if ( !$("body").hasClass("frontpage") ) { return; }
            $("#content a").ajaxifyAnchors(this_site.pageLoader);

            $(".area-images").reorder();
            // Fade area images
            $(".area-images").cycle({
                fx: 'fade',
                speed: 2500,
                timeout: 6000
            });
        };

        this.initArchiveContentList = function() {
            this.initContentListScroller();

            $(".contentlist a").click(function() {
                // The slug of the clicked item is stored in the markup
                var slug = $(this).parents(".content").find(".slug").html();
                // Store the URL of the archive page we are on
                var cameFrom = $("#page-permalink a").attr("href");

                // When clicking an archive item, the item shall be shown
                // "in the archive" - the navigation shall NOT change to the
                // category of the item! When the item is display "in the archive"
                // a "back to archive" buttons is displayed beneath. To make it
                // work we need to append something to the origin URL, otherwise
                // the PageLoader.load() method will not load because it is
                // already at the same URL (in the archive). We simple append
                // an anchor index to the URL.
                cameFrom += "#1";

                // Store the URL of the archive item for faking the permalink
                var permalink_url = $(this).attr("href");

                $.get( "/contentdetails/" + slug + "/",
                    function(data) {
                        $("#contentlist-container").slideUp("normal", function() {
                            var $data = $(data);
                            $data.hide();
                            $(this).replaceWith($data);

                            $data.slideDown("normal", function() {
                                this_site.initImageListscroller();

                                // Adjust the permalink
                                $("#page-permalink a").attr("href", permalink_url);

                                // Append a "Back to archive link"
                                $("#contentdetails-container")
                                    .after("<div class='back-to-archive'><a href='#'>&laquo; Zurück zum Archiv</a></div>")
                                    .next("div.back-to-archive").slideDown()
                                        .find("a")
                                        .click( function() {
                                            this_site.pageLoader.load(cameFrom);
                                            return false;
                                        });
                                        //.anchorOverlay();

                                // Update the document title
                                var contentTitle = $data.find("h3").eq(0).html();
                                var newDocumentTitle = "JAZZUNIQUE - ARCHIV - " +  contentTitle;
                                document.title = newDocumentTitle;

                            });
                        });
                    }
                );
                return false;
            });
        };

        this.initNewsletterForm = function() {
            if( $("body").hasClass("newsletterpage") ) {

                var newsletterSubscribeOpts = {
                    submitBtn: $("#newsletter-subscribe-form button"),
                    rules: { email: {required: true, email: true} },
                    messages: { email: "Bitte eine gültige E-Mail Adresse eingeben."},
                    submitHandler: function(form) {
                        $.post(
                            "/newsletter/",
                            { subscribe: true,
                              email: $("#newsletter-subscribe-form input").val() },
                            function (data, textStatus) {
                                $("#newsletter-subscribe-form")
                                    .empty()
                                    .append("<p>Ihre Daten wurden erfolgreich übermittelt.</p>");
                            }
                        );
                    }
                };
                $("#newsletter-subscribe-form").validate(newsletterSubscribeOpts);

                var newsletterUnsubscribeOpts = {
                    submitBtn: $("#newsletter-unsubscribe-form button"),
                    rules: { email: {required: true, email: true} },
                    messages: { email: "Bitte eine gültige E-Mail Adresse eingeben."},
                    submitHandler: function(form) {
                        $.post(
                            "/newsletter/",
                            { unsubscribe: true,
                              email: $("#newsletter-unsubscribe-form input").val() },
                            function (data, textStatus) {
                                $("#newsletter-unsubscribe-form")
                                    .empty()
                                    .append("<p>Ihre Daten wurden erfolgreich übermittelt.</p>");
                            }
                        );
                    }
                };
                $("#newsletter-unsubscribe-form").validate(newsletterUnsubscribeOpts);
            }
        };

        this.initMembersDetailPage = function() {
            if( $("body").hasClass("membersdetailpage") ) {
                $("#viewport ul li a").lightBox({
                    imageLoading: '/media/cms/css/jquery-lightbox/images/loading.gif',
                    imageBtnClose:'/media/cms/css/jquery-lightbox/images/close.gif',
                    imageBtnPrev: '/media/cms/css/jquery-lightbox/images/prev.gif',
                    imageBtnNext: '/media/cms/css/jquery-lightbox/images/next.gif'
                });
            }
        };
    }

    /** PageLoader

        The PageLoader class is used as a singleton (this is not a requirment)
        and loads and dispatches pages.
      */
    function PageLoader(options) {
        // Constructor code
        this.options = options;

        this.pageUrl = options.pageUrl;

        // ----------------------- Priviliged functions ----------------------

        /* Loads the page identified by ``pageUrl``.
         */
        this.load = function (pageUrl) {
            // console.log("Loading page: " + pageUrl + "current=" + this.pageUrl);
            var self = this;
            if (pageUrl === undefined) { pageUrl = this.pageUrl; }

            if (pageUrl === this.pageUrl) { return false; }

            $.ajax({url: pageUrl,
                    dataType: "html",   // using "xml" here results in a jQuery parseerror?!
                    success: function (htmlData) {
                        // Determine the 'class' of the loaded page. Is it a
                        // flatpage, a list page or a detail page?

                        // For some magic reasons the #pageclass element must not be the
                        // first child of the body but rather has to be contained in the
                        // "#container" element. This seems like a jQuery bug.
                        var pageClass = $(htmlData).find("#pageclass").text();

                        // The <body>-element is not part of the jquery-wrapped html
                        // data - i dont't understand this! To workaround this problem
                        // we are using a regexp to get the value of the <body> class
                        // attribute of the loaded page.
                        var bodyClassMatch = htmlData.search(/body class="(.*)"/);
                        var bodyClass = (bodyClassMatch != -1) ? RegExp.$1 : "bodyclass not found";

                        switch (pageClass) {
                            case "pageclass-flatpage":
                                // console.log("load(): loaded flatpage..");
                                if (self.options.pageLoaded) {
                                    self.options.pageLoaded(pageUrl, htmlData, pageClass, bodyClass);
                                }
                                break;
                            case "pageclass-listpage":
                                // console.log("load(): loaded listpage..");
                                if (self.options.pageLoaded) {
                                    self.options.pageLoaded(pageUrl, htmlData, pageClass, bodyClass);
                                }
                                break;
                            case "pageclass-detailpage":
                                // console.log("load(): loaded detailpage..");
                                break;
                            default:
                                // console.log("load(): unknown pageclass '" + pageClass + "''");
                                self.options.pageLoaded(pageUrl, htmlData, pageClass, bodyClass);
                                break;
                        }

                        // Store the new page url
                        self.pageUrl = pageUrl;
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
/*                        console.log("Load error '" + pageUrl + "'\n errorThrown: " + errorThrown +
                                                                "\n textStatus: " + textStatus +
                                                                "\n XMLHttpRequest: " + XMLHttpRequest);*/
                    }
            });

        };

    }

    var juSite = new JazzuniqueSite();
    juSite.init();

});
