/*
* kidsCarousel - A feature rotator for awesome people
*   http://pbskids.org/pbskidswidgets/carousel.html
*
* Copyright (c) 2009 PBS KIDS (http://pbskids.org)
* Written by Nate Eagle
*
* Built on top of the jQuery library
*   http://jquery.com
*
*/

(function ($) {
    // Plugin Definition
    jQuery.fn.kidsCarousel = function (options) {

        // Extend our default options with those provided.
        // Note that the first arg to extend is an empty object -
        // this is to keep from overriding our "defaults" object.
        var opts = jQuery.extend({}, jQuery.fn.kidsCarousel.defaults, options);

        // Our plugin implementation code goes here.

        var element = this;

        jQuery(window).load(function () {
            return element.each(function () {
                var carousel = this;
                var $this = jQuery(this);

                var panelWidth;
                var panelExtraWidth;
                var numChildren;

                // Give all interior elements the class "panel"
                var $panels = $this.children(opts.panel);
                $panels.addClass('panel');
                // Wrap the children in a single, larger div
                $this.wrapInner('<div class="kidsCarouselStrip"></div>');
                var $strip = $this.children('.kidsCarouselStrip');

                // Set the width of panels to be equal to the width of the container element
                panelWidth = $this.width();

                // Create an array to tally up the total extra width elements (padding, margin, border) for panels
                var panelExtraWidthArray = new Array();
                panelExtraWidthArray[0] = parseInt($panels.css('padding-left'));
                panelExtraWidthArray[1] = parseInt($panels.css('padding-right'));
                panelExtraWidthArray[2] = parseInt($panels.css('margin-left'));
                panelExtraWidthArray[3] = parseInt($panels.css('margin-right'));
                panelExtraWidthArray[4] = parseInt($panels.css('border-left-width'));
                panelExtraWidthArray[5] = parseInt($panels.css('border-right-width'));

                panelExtraWidth = 0;
                for (var i = 0; i < panelExtraWidthArray.length; i++) {
                    // If any item is not a number (ie "auto"), set it to zero
                    if (isNaN(panelExtraWidthArray[i]) == true) {
                        panelExtraWidthArray[i] = 0;
                    }
                    // Make sure the variable is a number
                    panelExtraWidthArray[i] = panelExtraWidthArray[i] * 1;
                    panelExtraWidth += panelExtraWidthArray[i];
                };

                // Calculate number of children
                numChildren = $strip.children().size();



                // Create styles that result from the above properties
                $strip.css({
                    'left': 0,
                    'position': 'absolute',
                    'top': 0 + $this.css('padding-top'),
                    'width': numChildren * panelWidth + 'px'
                });

                $panels.css({
                    'display': 'inline',
                    'float': 'left',
                    'width': panelWidth - panelExtraWidth + 'px'
                });

                $this.css({
                    'overflow': 'hidden',
                    'position': 'relative'
                });

                $this.css({
                    'height': $strip.height() + 'px'
                });

                var startChild;
                if (opts.randomStart == true) {
                    startChild = Math.floor((Math.random() * numChildren) + 1);
                } else {
                    startChild = 1;
                }
                $strip.css({
                    'left': -((startChild * panelWidth) - panelWidth) + 'px'
                });

                // Create navigation if enabled
                // var $navigation;
                // var $panelNavigation;

                if (opts.navigation == true) {
                    // Relative Navigation (ie back, forward)
                    if (opts.relativeNav == true) {
                        $this.append('<div class="kidsCarouselNavigation"><a href="" class="back">' + opts.relativeNavButtons[0] + '</a><span class="kidsCarouselNavigationList"></span><a href="" class="forward">' + opts.relativeNavButtons[1] + '</a></div>');
                    } else {
                        // No Relative Navigation
                        $this.append('<div class="kidsCarouselNavigation"><span class="kidsCarouselNavigationList"></span></div>');
                    };

                    var $navigation = $this.children('.kidsCarouselNavigation');
                    var $relativeNavBack = $navigation.children('a.back');
                    var $relativeNavForward = $navigation.children('a.forward');

                    $navigation.children('a').css({
                        'display': 'block',
                        'float': 'left'
                    });

                    var $panelNavigation = $navigation.children('.kidsCarouselNavigationList');

                    // Create panel navigation if enabled
                    if (opts.panelNav == true) {
                        // Create panel nav pulled from panel titles
                        if (opts.panelNavType == 'title') {
                            var $titles = $panels.children(opts.panelTitle);
                            $titles.each(function (i) {
                                var titleText;
                                if (jQuery(this).attr('title') != '') {
                                    titleText = jQuery(this).attr('title');
                                } else {
                                    titleText = jQuery(this).text();
                                }
                                $panelNavigation.append('<a href="#">' + titleText + '</a>');
                            });
                        }

                        // Create panel nav of numbers
                        if (opts.panelNavType == 'number') {
                            $titles = $panels.children(opts.panelTitle);
                            $titles.each(function (i) {
                                $panelNavigation.append('<a href="#">' + (i + 1) + '</a>');
                            });
                        }
                        var $panelNavigationLinks = $panelNavigation.children('a');
                        $panelNavigation.children().css({
                            'display': 'block',
                            'float': 'left'
                        });
                    };

                };

                var innerCarouselWidth = $this.width() + parseInt($this.css('padding-left')) + parseInt($this.css('padding-right'));
                var extraNavigationWidth = parseInt($navigation.outerWidth(true)) - parseInt($navigation.width());
                $navigation.css({
                    'bottom': 0,
                    'float': 'left',
                    'left': 0,
                    'position': 'absolute',
                    'width': innerCarouselWidth - extraNavigationWidth + 'px'
                });
                $this.css({
                    'padding-bottom': parseInt($this.css('padding-bottom')) + $navigation.outerHeight(true) + 'px'
                });

                $panelNavigation.children('a:nth-child(' + startChild + ')').addClass('current');

                addClickEvents(this);

                if (opts.autoAdvance == true) {
                    // Initialize autoadvance
                    beginAutoAdvance(this, opts.delay);

                    // Pause autoadvance on hover
                    $this.mouseover(function () {
                        clearTimeout(autoAdvanceTimer);
                    });
                    // Resume autoadvance on mouseout
                    $this.mouseout(function () {
                        beginAutoAdvance(this, opts.delay);
                    });
                };



                var autoAdvanceTimer;

                //
                // Private Functions
                // 
                function beginAutoAdvance(carousel, delay) {
                    autoAdvanceTimer = setTimeout(function () {
                        slide(carousel, 'forward', true, delay);
                    }, delay);
                    /* autoAdvanceTimer = setTimeout(function() {
                    slide(carousel, 'forward', true);
                    }, delay); */
                    // alert(autoAdvanceTimer);
                }

                function addClickEvents(carousel) {
                    var $back = jQuery(carousel).children('.kidsCarouselNavigation').children('a.back');
                    var $forward = jQuery(carousel).children('.kidsCarouselNavigation').children('a.forward');
                    var $navlinks = jQuery(carousel).children('.kidsCarouselNavigation').children('.kidsCarouselNavigationList').children('a');

                    if (opts.relativeNavCustomButtons[0] != null) {
                        var $customBack = jQuery(opts.relativeNavCustomButtons[0]);
                        var $customForward = jQuery(opts.relativeNavCustomButtons[1]);

                        $customBack.click(function () {
                            slide(carousel, 'backward', false);
                            return false;
                        });

                        $customForward.click(function () {
                            slide(carousel, 'forward', false);
                            return false;
                        });
                    };

                    $back.click(function () {
                        slide(carousel, 'backward', false);
                        return false;
                    });

                    $forward.click(function () {
                        slide(carousel, 'forward', false);
                        return false;
                    });

                    $navlinks.each(function (i) {
                        jQuery(this).click(function () {
                            slide(carousel, 'forward', false, 0, i + 1);
                            return false;
                        });
                    });
                }

                function removeClickEvents(carousel) {
                    var $back = jQuery(carousel).children('.kidsCarouselNavigation').children('a.back');
                    var $forward = jQuery(carousel).children('.kidsCarouselNavigation').children('a.forward');
                    var $navlinks = jQuery(carousel).children('.kidsCarouselNavigation').children('.kidsCarouselNavigationList').children('a');

                    if (opts.relativeNavCustomButtons[0] != null) {
                        var $customBack = jQuery(opts.relativeNavCustomButtons[0]);
                        var $customForward = jQuery(opts.relativeNavCustomButtons[1]);

                        $customBack.unbind('click');
                        $customForward.unbind('click');

                        $customBack.click(function () {
                            return false;
                        });

                        $customForward.click(function () {
                            return false;
                        });
                    };

                    $back.unbind('click');
                    $forward.unbind('click');
                    $navlinks.unbind('click');
                    $back.click(function () {
                        return false;
                    });
                    $forward.click(function () {
                        return false;
                    });
                    $navlinks.each(function (i) {
                        jQuery(this).click(function () {
                            return false;
                        });
                    });
                };

                function slide(carousel, direction, auto, delay, destination) {

                    clearTimeout(autoAdvanceTimer);

                    if (typeof auto == 'undefined') auto = true;
                    if (typeof delay == 'undefined') delay = 0;
                    if (typeof destination == 'undefined') { destination = 'undefined' };

                    removeClickEvents(carousel);

                    // alert(carousel);
                    var $carousel = jQuery(carousel);
                    var panelWidth = $carousel.width();
                    var $strip = jQuery(carousel).children('.kidsCarouselStrip');
                    var $navigation = $carousel.children('.kidsCarouselNavigation');
                    var $panelNavigation = $navigation.children('.kidsCarouselNavigationList');

                    var position = $strip.position();
                    var currentChild = Math.ceil(Math.abs(position.left - panelWidth) / panelWidth);
                    var totalChildren = $strip.width() / panelWidth;
                    var nextPosition;

                    // Do nothing if already at destination
                    if (currentChild == destination) {
                        addClickEvents(carousel);
                        return false;
                    }

                    // Set nextChild for forward and back buttons
                    if (destination == 'undefined') {
                        if (direction == 'forward') {
                            destination = currentChild + 1;
                        } else {
                            destination = currentChild - 1;
                        };
                    }

                    // Set nextPosition
                    nextPosition = -((destination * panelWidth) - panelWidth);

                    if (destination > totalChildren || destination < 1) {
                        $strip.clone().prependTo(carousel);
                        var cloneDestination;

                        if (destination > totalChildren) {
                            $carousel.children('.kidsCarouselStrip:nth-child(2)').css({ 'left': panelWidth + 'px' });
                            cloneDestination = 0;
                        } else {
                            $carousel.children('.kidsCarouselStrip:nth-child(2)').css({ 'left': -($strip.width()) + 'px' });
                            cloneDestination = -($strip.width() - panelWidth);
                        }

                        $carousel.children('.kidsCarouselStrip:nth-child(1)').animate({ 'left': nextPosition + 'px' }, 'slow', function () {
                            $carousel.children('.kidsCarouselStrip:nth-child(1)').remove();
                            addClickEvents(carousel);
                        });
                        $carousel.children('.kidsCarouselStrip:nth-child(2)').animate({ 'left': cloneDestination + 'px' }, 'slow');
                    } else {
                        $strip.animate({ 'left': nextPosition + 'px' }, 'slow', function () {
                            addClickEvents(carousel);
                        });
                    }


                    $panelNavigation.children('a.current').removeClass('current');

                    if (destination > totalChildren) { destination = 1; }
                    if (destination < 1) { destination = totalChildren; }

                    $panelNavigation.children('a:nth-child(' + destination + ')').addClass('current');

                    if (auto == true) { beginAutoAdvance(carousel, delay); };

                }


            });

        });
    };



    //
    // Plugin defaults
    //
    jQuery.fn.kidsCarousel.defaults = {
        autoAdvance: true,
        delay: 7000,
        navigation: true,
        panel: 'div',
        panelNav: true,
        panelNavType: 'title',
        panelTitle: 'h4',
        randomStart: true,
        relativeNav: true,
        relativeNavButtons: ['Back', 'Forward'],
        relativeNavCustomButtons: [null, null]
    };

    // End of Closure
})(jQuery);
