; (function ($, window, document, undefined) {

'use strict';

var noop = function () {
};

var Orbit = function (el, settings) {
    // Don't reinitialize plugin
    if (el.hasClass(settings.slides_container_class)) {
        return this;
    }

    var self = this,
        container,
        slides_container = el,
        number_container,
        bullets_container,
        timer_container,
        idx = 0,
        animate,
        timer,
        locked = false,
        adjust_height_after = false;

    self.slides = function () {
        return slides_container.children(settings.slide_selector);
    };

    self.slides().first().addClass(settings.active_slide_class);

    self.update_slide_number = function (index) {
        if (settings.slide_number) {
            number_container.find('span:first').text(parseInt(index) + 1);
            number_container.find('span:last').text(self.slides().length);
        }
        if (settings.bullets) {
            bullets_container.children().removeClass(settings.bullets_active_class);
            $(bullets_container.children().get(index)).addClass(settings.bullets_active_class);
        }
    };

    self.update_active_link = function (index) {
        var link = $('[data-orbit-link="' + self.slides().eq(index).attr('data-orbit-slide') + '"]');
        link.siblings().removeClass(settings.bullets_active_class);
        link.addClass(settings.bullets_active_class);
    };

    self.build_markup = function () {
        slides_container.wrap('<div class="' + settings.container_class + '"></div>');
        container = slides_container.parent();
        slides_container.addClass(settings.slides_container_class);

        if (settings.stack_on_small) {
            container.addClass(settings.stack_on_small_class);
        }

        if (settings.navigation_arrows) {
            container.append($('<a href="#"><span></span></a>').addClass(settings.prev_class));
            container.append($('<a href="#"><span></span></a>').addClass(settings.next_class));
        }

        if (settings.timer) {
            timer_container = $('<div>').addClass(settings.timer_container_class);
            timer_container.append('<span>');
            timer_container.append($('<div>').addClass(settings.timer_progress_class));
            timer_container.addClass(settings.timer_paused_class);
            container.append(timer_container);
        }

        if (settings.slide_number) {
            number_container = $('<div>').addClass(settings.slide_number_class);
            number_container.append('<span></span> ' + settings.slide_number_text + ' <span></span>');
            container.append(number_container);
        }

        if (settings.bullets) {
            bullets_container = $('<ol>').addClass(settings.bullets_container_class);
            container.append(bullets_container);
            bullets_container.wrap('<div class="orbit-bullets-container"></div>');
            self.slides().each(function (idx, el) {
                var bullet = $('<li>').attr('data-orbit-slide', idx).on('click', self.link_bullet);
                ;
                bullets_container.append(bullet);
            });
        }

    };

    self._goto = function (next_idx, start_timer) {
        // if (locked) {return false;}
        if (next_idx === idx) {
            return false;
        }
        if (typeof timer === 'object') {
            timer.restart();
        }
        var slides = self.slides();

        var dir = 'next';
        locked = true;
        if (next_idx < idx) {
            dir = 'prev';
        }
        if (next_idx >= slides.length) {
            if (!settings.circular) return false;
            next_idx = 0;
        } else if (next_idx < 0) {
            if (!settings.circular) return false;
            next_idx = slides.length - 1;
        }

        var current = $(slides.get(idx));
        var next = $(slides.get(next_idx));

        current.css('zIndex', 2);
        current.removeClass(settings.active_slide_class);
        next.css('zIndex', 4).addClass(settings.active_slide_class);

        slides_container.trigger('before-slide-change.fndtn.orbit');
        settings.before_slide_change();
        self.update_active_link(next_idx);

        var callback = function () {
            var unlock = function () {
                idx = next_idx;
                locked = false;
                if (start_timer === true) {
                    timer = self.create_timer();
                    timer.start();
                }
                self.update_slide_number(idx);
                slides_container.trigger('after-slide-change.fndtn.orbit', [{
                    slide_number: idx,
                    total_slides: slides.length
                }]);
                settings.after_slide_change(idx, slides.length);
            };
            if (slides_container.height() != next.height() && settings.variable_height) {
                slides_container.animate({'height': next.height()}, 250, 'linear', unlock);
            } else {
                unlock();
            }
        };

        if (slides.length === 1) {
            callback();
            return false;
        }

        var start_animation = function () {
            if (dir === 'next') {
                animate.next(current, next, callback);
            }
            if (dir === 'prev') {
                animate.prev(current, next, callback);
            }
        };

        if (next.height() > slides_container.height() && settings.variable_height) {
            slides_container.animate({'height': next.height()}, 250, 'linear', start_animation);
        } else {
            start_animation();
        }
    };

    self.next = function (e) {
        e.stopImmediatePropagation();
        e.preventDefault();
        self._goto(idx + 1);
    };

    self.prev = function (e) {
        e.stopImmediatePropagation();
        e.preventDefault();
        self._goto(idx - 1);
    };

    self.link_custom = function (e) {
        e.preventDefault();
        var link = $(this).attr('data-orbit-link');
        if ((typeof link === 'string') && (link = $.trim(link)) != '') {
            var slide = container.find('[data-orbit-slide=' + link + ']');
            if (slide.index() != -1) {
                self._goto(slide.index());
            }
        }
    };

    self.link_bullet = function (e) {
        var index = $(this).attr('data-orbit-slide');
        if ((typeof index === 'string') && (index = $.trim(index)) != '') {
            if (isNaN(parseInt(index))) {
                var slide = container.find('[data-orbit-slide=' + index + ']');
                if (slide.index() != -1) {
                    self._goto(slide.index() + 1);
                }
            }
            else {
                self._goto(parseInt(index));
            }
        }

    }

    self.timer_callback = function () {
        self._goto(idx + 1, true);
    }

    self.compute_dimensions = function () {
        var current = $(self.slides().get(idx));
        var h = current.height();
        if (!settings.variable_height) {
            self.slides().each(function () {
                if ($(this).height() > h) {
                    h = $(this).height();
                }
            });
        }
        slides_container.height(h);
    };

    self.create_timer = function () {
        var t = new Timer(
            container.find('.' + settings.timer_container_class),
            settings,
            self.timer_callback
        );
        return t;
    };

    self.stop_timer = function () {
        if (typeof timer === 'object') timer.stop();
    };

    self.toggle_timer = function () {
        var t = container.find('.' + settings.timer_container_class);
        if (t.hasClass(settings.timer_paused_class)) {
            if (typeof timer === 'undefined') {
                timer = self.create_timer();
            }
            timer.start();
        }
        else {
            if (typeof timer === 'object') {
                timer.stop();
            }
        }
    };

    self.init = function () {
        self.build_markup();
        if (settings.timer) {
            timer = self.create_timer();
            Foundation.utils.image_loaded(this.slides().children('img'), timer.start);
        }
        animate = new FadeAnimation(settings, slides_container);
        if (settings.animation === 'slide')
            animate = new SlideAnimation(settings, slides_container);

        container.on('click', '.' + settings.next_class, self.next);
        container.on('click', '.' + settings.prev_class, self.prev);

        if (settings.next_on_click) {
            container.on('click', '.' + settings.slides_container_class + ' [data-orbit-slide]', self.link_bullet);
        }

        container.on('click', self.toggle_timer);
        if (settings.swipe) {
            container.on('touchstart.fndtn.orbit', function (e) {
                if (!e.touches) {
                    e = e.originalEvent;
                }
                var data = {
                    start_page_x: e.touches[0].pageX,
                    start_page_y: e.touches[0].pageY,
                    start_time: (new Date()).getTime(),
                    delta_x: 0,
                    is_scrolling: undefined
                };
                container.data('swipe-transition', data);
                e.stopPropagation();
            })
                .on('touchmove.fndtn.orbit', function (e) {
                    if (!e.touches) {
                        e = e.originalEvent;
                    }
                    // Ignore pinch/zoom events
                    if (e.touches.length > 1 || e.scale && e.scale !== 1) return;

                    var data = container.data('swipe-transition');
                    if (typeof data === 'undefined') {
                        data = {};
                    }

                    data.delta_x = e.touches[0].pageX - data.start_page_x;

                    if (typeof data.is_scrolling === 'undefined') {
                        data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
                    }

                    if (!data.is_scrolling && !data.active) {
                        e.preventDefault();
                        var direction = (data.delta_x < 0) ? (idx + 1) : (idx - 1);
                        data.active = true;
                        self._goto(direction);
                    }
                })
                .on('touchend.fndtn.orbit', function (e) {
                    container.data('swipe-transition', {});
                    e.stopPropagation();
                })
        }
        container.on('mouseenter.fndtn.orbit', function (e) {
            if (settings.timer && settings.pause_on_hover) {
                self.stop_timer();
            }
        })
            .on('mouseleave.fndtn.orbit', function (e) {
                if (settings.timer && settings.resume_on_mouseout) {
                    timer.start();
                }
            });

        $(document).on('click', '[data-orbit-link]', self.link_custom);
        $(window).on('load resize', self.compute_dimensions);
        Foundation.utils.image_loaded(this.slides().children('img'), self.compute_dimensions);
        Foundation.utils.image_loaded(this.slides().children('img'), function () {
            container.prev('.' + settings.preloader_class).css('display', 'none');
            self.update_slide_number(0);
            self.update_active_link(0);
            slides_container.trigger('ready.fndtn.orbit');
        });
    };

    self.init();
};

var Timer = function (el, settings, callback) {
    var self = this,
        duration = settings.timer_speed,
        progress = el.find('.' + settings.timer_progress_class),
        start,
        timeout,
        left = -1;

    this.update_progress = function (w) {
        var new_progress = progress.clone();
        new_progress.attr('style', '');
        new_progress.css('width', w + '%');
        progress.replaceWith(new_progress);
        progress = new_progress;
    };

    this.restart = function () {
        clearTimeout(timeout);
        el.addClass(settings.timer_paused_class);
        left = -1;
        self.update_progress(0);
    };

    this.start = function () {
        if (!el.hasClass(settings.timer_paused_class)) {
            return true;
        }
        left = (left === -1) ? duration : left;
        el.removeClass(settings.timer_paused_class);
        start = new Date().getTime();
        progress.animate({'width': '100%'}, left, 'linear');
        timeout = setTimeout(function () {
            self.restart();
            callback();
        }, left);
        el.trigger('timer-started.fndtn.orbit')
    };

    this.stop = function () {
        if (el.hasClass(settings.timer_paused_class)) {
            return true;
        }
        clearTimeout(timeout);
        el.addClass(settings.timer_paused_class);
        var end = new Date().getTime();
        left = left - (end - start);
        var w = 100 - ((left / duration) * 100);
        self.update_progress(w);
        el.trigger('timer-stopped.fndtn.orbit');
    };
};

var SlideAnimation = function (settings, container) {
    var duration = settings.animation_speed;
    var is_rtl = ($('html[dir=rtl]').length === 1);
    var margin = is_rtl ? 'marginRight' : 'marginLeft';
    var animMargin = {};
    animMargin[margin] = '0%';

    this.next = function (current, next, callback) {
        current.animate({marginLeft: '-100%'}, duration);
        next.animate(animMargin, duration, function () {
            current.css(margin, '100%');
            callback();
        });
    };

    this.prev = function (current, prev, callback) {
        current.animate({marginLeft: '100%'}, duration);
        prev.css(margin, '-100%');
        prev.animate(animMargin, duration, function () {
            current.css(margin, '100%');
            callback();
        });
    };
};

var FadeAnimation = function (settings, container) {
    var duration = settings.animation_speed;
    var is_rtl = ($('html[dir=rtl]').length === 1);
    var margin = is_rtl ? 'marginRight' : 'marginLeft';

    this.next = function (current, next, callback) {
        next.css({'margin': '0%', 'opacity': '0.01'});
        next.animate({'opacity': '1'}, duration, 'linear', function () {
            current.css('margin', '100%');
            callback();
        });
    };

    this.prev = function (current, prev, callback) {
        prev.css({'margin': '0%', 'opacity': '0.01'});
        prev.animate({'opacity': '1'}, duration, 'linear', function () {
            current.css('margin', '100%');
            callback();
        });
    };
};

Foundation.libs = Foundation.libs || {};

Foundation.libs.orbit = {
    name: 'orbit',

    version: '5.5.0',

    settings: {
        animation: 'slide',
        timer_speed: 10000,
        pause_on_hover: true,
        resume_on_mouseout: false,
        next_on_click: true,
        animation_speed: 500,
        stack_on_small: false,
        navigation_arrows: true,
        slide_number: true,
        slide_number_text: 'of',
        container_class: 'orbit-container',
        stack_on_small_class: 'orbit-stack-on-small',
        next_class: 'orbit-next',
        prev_class: 'orbit-prev',
        timer_container_class: 'orbit-timer',
        timer_paused_class: 'paused',
        timer_progress_class: 'orbit-progress',
        slides_container_class: 'orbit-slides-container',
        preloader_class: 'preloader',
        slide_selector: '*',
        bullets_container_class: 'orbit-bullets',
        bullets_active_class: 'active',
        slide_number_class: 'orbit-slide-number',
        caption_class: 'orbit-caption',
        active_slide_class: 'active',
        orbit_transition_class: 'orbit-transitioning',
        bullets: true,
        circular: true,
        timer: true,
        variable_height: false,
        swipe: true,
        before_slide_change: noop,
        after_slide_change: noop
    },

    init: function (scope, method, options) {
        var self = this;
        this.bindings(method, options);
    },

    events: function (instance) {
        var orbit_instance = new Orbit(this.S(instance), this.S(instance).data('orbit-init'));
        this.S(instance).data(this.name + '-instance', orbit_instance);
    },

    reflow: function () {
        var self = this;

        if (self.S(self.scope).is('[data-orbit]')) {
            var $el = self.S(self.scope);
            var instance = $el.data(self.name + '-instance');
            instance.compute_dimensions();
        } else {
            self.S('[data-orbit]', self.scope).each(function (idx, el) {
                var $el = self.S(el);
                var opts = self.data_options($el);
                var instance = $el.data(self.name + '-instance');
                instance.compute_dimensions();
            });
        }
    }
};

}(jQuery, window, window.document));