/*
Title :: adidoCarousel
Author :: Thomas Stradling
Version :: 0.3.3

Changelog ::

0.1 ::

Basic implementation of the solution.

 - Sliding carousel animation.
 - Allows the definition on animation style (default: easeInOutExpo).
 - Allows for use of next / previous buttons.
   Button use controlled by 'buttons' parameter (default: true)
   Also allows control over which elements are designated as buttons
   using buttonNext and buttonPrev parameters.
 - Added clickContinue option.
   Allows carousel to continue cycling after user clicks on a button
   when set to true (default: false).
 - Option speed
   Sets the pause between animations in miliseconds.

INCOMPLETE

 - buildFrameWork

0.2 ::

 - Added pager system
 - Option pagerElement
   Specifies an element containing a <ul> to be referenced.
 - Adds class 'aCarousel' to carousel item.

0.2.1 ::

 - Option startPosition
   Sets an offset for the carousel to start on.

0.3 ::

 - Added option: horizontal (boolean | true)
   Controls the direction of scrolling for the carousel.
   Default behaviour is horizontal scrolling.

 - Added new 'fade' animation.
 - Added option: mode (string | 'slide')
   Controls the animation method to use, currently either 'slide' or
   fade, if invalid value specified defaults to 'slide'.

 - adidoCarousel can now be used to power a image slide show.
   There should only be one image per <li> in the carousel.
   When the carousel moves it searches current <li> for an <img> and gets
   the src attribute, then transfers the src to the designated large
   image target.
 - Added option: imgLarge (boolean | false)
   Controls whether to use the slide show option.
 - Added option: imgContainer (string | '.imgContainer')
   Designates the element to be used for the large image.

 - Added option: step (integer | 1)
   Gives the option allowing the carousel to step through multiple slides
   at a time.

INCOMPLETE

wrap
   

0.3.1 ::

 - Using $pager to hold pagerElement jQuery object.
 - Added option: resizeMask (boolean | false)
   If enabled causes the parent of the plugin object to be resized
   according to the height of the tallest <li> item in the carousel
   list.

0.3.2 ::

 - Added option: hoverPause (boolean | false)
   When enabled pauses the carousel on a hover event and restarts it on the hover exit.

0.3.2a ::

 - Added option: pagerHover (boolean | false)
   If this is enabled when a user hovers over a pager element it will become the active
   element, and will select the corresponding carousel item.

0.3.3 ::

 - Rewritten passing through extra variables to the moveCarousel function using an array.
 - Rewritten fade animation, more natural effect.
   Includes an initial setup for fade animation allowing for the different.
 
 - Various parts of this release are still being worked on.
    - pagerHoverAnimations
    - pagerHover bugs
    
 - Added option: pagerAnim (boolean | false)
   Replaces previous pager animation options. Setting to true causes all aspects of
   pager to animate.
   
0.3.4 ::

 - Added option: dynamicResize (boolean | false)
 
0.3.5 ::

0.3.6 ::
0.3.6 - pre 1 ::
0.3.6 - pre 2 ::
0.3.6 - pre 3 ::
0.3.6 - pre 4 ::
0.3.6 - pre 5 ::
  - Added custom option for declaring next/previous buttons.
    Allows for buttons relative to the root element.
  
  - Added animInstant to the initial setup section.
    If the startPosition is non-standard shifts the carousel to the appropriate starting position.
   
*/

//
(function($) {
    //
    $.fn.adidoCarousel = function(options) {
        var opts = $.extend({}, $.fn.adidoCarousel.defaults, options);
        return this.each(function() {
            jQuery.easing.def = opts.anim;
            var $this = $(this);

            if (!$this.hasClass('aCarousel')) {
                $this.addClass('aCarousel');
            }

            /* List count */var lc = $this.children('li').size();
            /* Current item index */var c = opts.startPosition;
            /* Offset */var os = -1 + opts.step;
            /* Rotation count */var r = lc - os;
            /* Rotation count */var r = r - (-1 + opts.minDisplay);

            /* info array */
            var _info = new Array();
            _info['lc'] = lc;
            _info['c'] = c;
            _info['os'] = os;
            _info['r'] = r;

            if (opts.horizontal) {
                var d = 'left';
                var ls = $this.children('li').eq(0).outerWidth();
                $this.width(lc * ls);
            } else {
                var d = 'top';
                var ls = $this.children('li').eq(0).outerHeight();
                $this.height(lc * ls);
            }

            _info['ls'] = ls;

            /* Modify size of the list */
            lc = lc - (-1 + opts.minDisplay);
            _info['lc'] = lc;

            if (opts.autoStart) {
                if (opts.startDelay > 0) {
                    var t = setTimeout(function() {
                        var carouselTimer = setInterval(function() {
                            if (c < r) {
                                c += opts.step;
                            } else {
                                c = opts.startPosition;
                            }
                            $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                        }, opts.speed);
                    }, opts.startDelay);
                } else {
                    var carouselTimer = setInterval(function() {
                        if (c < r) {
                            c += opts.step;
                        } else {
                            c = opts.startPosition;
                        }
                        $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                    }, opts.speed);
                }
            }

            if (opts.buttons) {

                if (opts.buttonNext == 'custom') {
                    var $btnNext = $.fn.adidoCarousel.btnNext($this);
                } else {
                    var $btnNext = $(opts.buttonNext);
                }

                $btnNext.click(function(e) {

                    e.preventDefault();

                    carouselTimer = window.clearInterval(carouselTimer);

                    if (opts.clickContinue) {
                        carouselTimer = setInterval(function() {
                            if (c < r) {
                                c += opts.step;
                            } else {
                                c = opts.startPosition;
                            }
                            $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                        }, opts.speed);
                    }

                    if (c < r) {
                        c += opts.step;
                    } else {
                        c = opts.startPosition;
                    }
                    $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                });
                if (opts.buttonPrev == 'custom') {
                    var $btnPrev = $.fn.adidoCarousel.btnPrev($this);
                } else {
                    var $btnPrev = $(opts.buttonPrev);
                }
                $btnPrev.click(function(e) {
                    e.preventDefault();

                    carouselTimer = window.clearInterval(carouselTimer);

                    if (opts.clickContinue) {
                        carouselTimer = setInterval(function() {
                            if (c < r) {
                                c += opts.step;
                            } else {
                                c = opts.startPosition;
                            }
                            $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                        }, opts.speed);
                    }

                    if (c > opts.startPosition) {
                        c -= opts.step;
                    } else {
                        c = r;
                    }
                    $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                });
            }

            if (opts.pager) {
                // Build a pager system for the carousel

                // Assigns the selector to a variable allowing easier access / faster performance(?).
                var $pager = $(opts.pagerElement);

                // Creates an un-ordered list automatically, and populates it with a <li> item for each <li> in the carousel.
                if (opts.pagerAuto) {
                    $pager.append('<ul></ul>');
                    var i = 0;
                    for (i = 0; i < lc; i++) {
                        var ps = '';
                        switch (opts.pagerStyle) {
                            case null:
                                ps = '';
                                break;
                            case 'numeric':
                                psi = i + 1;
                                ps = '' + psi;
                                break;
                            default:
                                ps = '';
                        }
                        $pager.children('ul').append('<li>' + ps + '</li>');
                    }
                }
                // Initialises the pager elements when first loaded.
                var n = c + 1;
                $pager.find('li:nth-child(' + n + ')').addClass('acpNext');
                $pager.find('li:nth-child(' + c + ')').addClass('acpActive');

                $pager.find('li').click(function() {
                    carouselTimer = window.clearInterval(carouselTimer);

                    if (opts.clickContinue) {
                        carouselTimer = setInterval(function() {
                            if (c < r) {
                                c += opts.step;
                            } else {
                                c = opts.startPosition;
                            }
                            $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                        }, opts.speed);
                    }
                    // Prevents jumping behaviour clicking on an item which is currently active.
                    if ($(this).hasClass('acpActive')) {
                        // Do Nothing
                    } else {
                        c = $pager.find('li').index(this);
                        c += 1;
                        $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                    }
                }).css('cursor', 'pointer');

                // If custom pager element uses <a> tag as part of the mark up disable default click.
                $pager.find('a').click(function(e) {
                    e.preventDefault();
                });

                var _pagerArray = new Array();

                if (opts.pagerHover) {
                    $pager.find('li').hover(function() {
                        var pi = $pager.find('li').index(this);
                        _pagerArray[pi] = true;
                        if (!opts.clickContinue) {
                            clearInterval(carouselTimer);
                        }
                        if (opts.pagerAnim) {
                            $(this).addClass('acpHover', 500);
                        } else {
                            $(this).addClass('acpHover');
                        }
                        var cp = $pager.find('li').index(this);
                        cp += 1;

                        window.setTimeout(function() {
                            if (_pagerArray[pi]) {
                                c = cp;
                                $.fn.adidoCarousel.moveCarousel($this, c, _info, opts);
                            }
                        }, 2000);

                    }, function() {
                        var pi = $pager.find('li').index(this);
                        _pagerArray[pi] = false;
                        if (opts.pagerAnim) {
                            $(this).removeClass('acpHover', 500);
                        } else {
                            $(this).removeClass('acpHover');
                        }

                    });
                }

            }

            if (opts.imgLarge) {
                var src = $this.children('li:nth-child(' + c + ')').find('img').attr('src');
                if ($(opts.imgContainer).find('img').size() == 0) {
                    $(opts.imgContainer).append('<img />')
                }
                $(opts.imgContainer).find('img').attr('src', src);
            }

            if (opts.resizeMask) {
                var h = 0;
                $this.children('li').each(function() {
                    var hh = $(this).outerHeight();
                    if (hh > h) {
                        h = hh;
                    }
                }).height(h);
                $this.parent().height(h);
                if (!opts.horizontal) {
                    _info['ls'] = h;
                }
            }

            if (opts.hoverPause) {
                $this.parent().hover(function() {
                    /*clearInterval(carouselTimer);*/
                    $this.addClass('hover');
                }, function() {
                    /*var carouselTimer = setInterval(function() {
                    if (c < r) {
                    c += opts.step;
                    } else {
                    c = opts.startPosition;
                    }
                    $.fn.adidoCarousel.moveCarousel($this, c, ls, opts);
                    }, opts.speed);*/
                    $this.removeClass('hover');
                });
            }

            if (opts.dynamicResize) {
                var h = $this.children('li:nth-child(' + c + ')').height();
                $this.parent().height(h);
            }

            /* Initial item setup */
            $this.children('li:nth-child(' + c + ')').addClass('acActive');

            switch (opts.mode) {
                case 'fade':
                    var fadeCSS = {
                        'left': '0',
                        'position': 'absolute',
                        'top': '0',
                        'z-index': '2'
                    };
                    $this.children('li').css(fadeCSS).hide();
                    $this.children('li:nth-child(' + c + ')').css('z-index', '6').show();
                    break;
            }

            $.fn.adidoCarousel.animInstant($this, c, _info['ls'], opts);
            //$.fn.adidoCarousel.animCallback($this, c, _info['ls'], opts);

        });
    };

    $.fn.adidoCarousel.defaults = {
        anim: 'easeInOutExpo',
        animDelay: 600,
        animSpeed: 400,
        autoStart: true,
        buttons: true,
        buttonNext: '.carouselNext',
        buttonPrev: '.carouselPrev',
        clickContinue: false,
        dynamicResize: false,
        horizontal: true,
        hoverPause: false,
        imgLarge: false,
        imgContainer: '.imgContainer',
        minDisplay: 1,
        mode: 'slide',
        pager: false,
        pagerAuto: true,
        pagerElement: '.carouselPager',
        pagerHover: false,
        pagerStyle: 'none',
        pagerAnim: false,
        resizeMask: false,
        speed: 5000,
        startDelay: 0,
        startPosition: 1,
        step: 1,
        wrap: false
    };

    $.fn.adidoCarousel.moveCarousel = function(e, c, _a, o) {
        e.children('.acActive').removeClass('acActive');
        e.children('li:nth-child(' + c + ')').addClass('acActive');
        switch (o.mode) {
            case 'slide':
                $.fn.adidoCarousel.animSlide(e, c, _a['ls'], o);
                break;

            case 'fade':
                $.fn.adidoCarousel.animFade(e, c, _a, o);
                break;

            case 'instant':
                $.fn.adidoCarousel.animInstant(e, c, _a['ls'], o);
                break;

            case 'custom':
                $.fn.adidoCarousel.animCustom(e, c, _a['ls'], o);
                break;

            default:
                /* If value is over-ridden with an incorrect mode it defaults to using 'slide' animation method */
                $.fn.adidoCarousel.animSlide(e, c, _a['ls'], o);
        }
        if (o.pager) {
            $.fn.adidoCarousel.movePager(o, c);
        }
        if (o.imgLarge) {
            var src = e.children('li:nth-child(' + c + ')').find('img').attr('src');
            if ($(o.imgContainer).find('img').size() == 0) {
                $(o.imgContainer).append('<img />')
            }
            $(o.imgContainer).find('img').attr('src', src);
        }
        if (o.dynamicResize) {
            var h = e.children('li:nth-child(' + c + ')').height();
            e.parent().height(h);
        }

    }

    $.fn.adidoCarousel.animFade = function(e, c, _a, o) {
        e.children('li').fadeOut(1300);
        e.children('li:nth-child(' + c + ')').hide().css('z-index', 6).delay(o.animDelay).fadeIn(1300, $.fn.adidoCarousel.animCallback(e, c, _a['ls'], o));
    }

    $.fn.adidoCarousel.animInstant = function(e, c, s, o) {
        if (o.horizontal) {
            e.css({
                left: -((c - 1) * s) + "px"
            });
            $.fn.adidoCarousel.animCallback(e, c, s, o);
        } else {
            e.css({
                top: -((c - 1) * s) + "px"
            });
            $.fn.adidoCarousel.animCallback(e, c, s, o);
        }
    }

    $.fn.adidoCarousel.animSlide = function(e, c, s, o) {
        if (o.horizontal) {
            e.stop().animate({
                left: -((c - 1) * s) + "px"
            }, 500, $.fn.adidoCarousel.animCallback(e, c, s, o));
        } else {
            e.stop().animate({
                top: -((c - 1) * s) + "px"
            }, 500, $.fn.adidoCarousel.animCallback(e, c, s, o));
        }
    }

    $.fn.adidoCarousel.movePager = function(o, c) {
        $e = $(o.pagerElement);
        $e.find('.acpActive').removeClass('acpActive');
        $e.find('.acpNext').removeClass('acpNext');
        var n = c + 1;
        if (o.pagerAnim) {
            $e.find('li:nth-child(' + n + ')').addClass('acpNext', 500);
            $e.find('li:nth-child(' + c + ')').addClass('acpActive', 500);
        } else {
            $e.find('li:nth-child(' + n + ')').addClass('acpNext');
            $e.find('li:nth-child(' + c + ')').addClass('acpActive');
        }
    }

    $.fn.adidoCarousel.btnNext = function(e) {
        return btn;
    }

    $.fn.adidoCarousel.btnPrev = function(e) {
        return btn;
    }

    $.fn.adidoCarousel.buildFrameWork = function(e) {
        // var w = $('<div class="carouselContainer"><div class="carouselFrame"></div></div>');
        e.wrap('<div class="carouselFrame"></div>');
        e.parent().wrap('<div class="carouselContainer"></div>');
        var a = $('<a href="#prev" class="carouselPrev">Previous</a> <a href="#next" class="carouselNext">Next</a>');
        e.parent().parent().append(a);
    }

    $.fn.adidoCarousel.setupLinear = function(e) {
    }

    $.fn.adidoCarousel.setupStack = function(e) {
    }

    $.fn.adidoCarousel.animCallback = function(e, c, s, o) {

    }

    $.fn.adidoCarousel.animCustom = function(e, c, s, o) {
        // e : plugin element
        // c : item count
        // s : element size
        // o : options


    }
    //
})(jQuery);
//
