;
(function ($, window, document, undefined) {
    'use strict';

    Foundation.libs['magellan-expedition'] = {
        name: 'magellan-expedition',

        version: '5.5.0',

        settings: {
            active_class: 'active',
            threshold: 0, // pixels from the top of the expedition for it to become fixes
            destination_threshold: 20, // pixels from the top of destination for it to be considered active
            throttle_delay: 30, // calculation throttling to increase framerate
            fixed_top: 0, // top distance in pixels assigend to the fixed element on scroll
            offset_by_height: true,  // whether to offset the destination by the expedition height. Usually you want this to be true, unless your expedition is on the side.
            duration: 700, // animation duration time
            easing: 'swing' // animation easing
        },

        init: function (scope, method, options) {
            Foundation.inherit(this, 'throttle');
            this.bindings(method, options);
        },

        events: function () {
            var self = this,
                S = self.S,
                settings = self.settings;

            // initialize expedition offset
            self.set_expedition_position();

            S(self.scope)
                .off('.magellan')
                .on('click.fndtn.magellan', '[' + self.add_namespace('data-magellan-arrival') + '] a[href^="#"]', function (e) {
                    e.preventDefault();
                    var expedition = $(this).closest('[' + self.attr_name() + ']'),
                        settings = expedition.data('magellan-expedition-init'),
                        hash = this.hash.split('#').join(''),
                        target = $('a[name="' + hash + '"]');

                    if (target.length === 0) {
                        target = $('#' + hash);

                    }


                    // Account for expedition height if fixed position
                    var scroll_top = target.offset().top - settings.destination_threshold + 1;
                    if (settings.offset_by_height) {
                        scroll_top = scroll_top - expedition.outerHeight();
                    }

                    $('html, body').stop().animate({
                        'scrollTop': scroll_top
                    }, settings.duration, settings.easing, function () {
                        if (history.pushState) {
                            history.pushState(null, null, '#' + hash);
                        }
                        else {
                            location.hash = '#' + hash;
                        }
                    });
                })
                .on('scroll.fndtn.magellan', self.throttle(this.check_for_arrivals.bind(this), settings.throttle_delay));

            $(window)
                .on('resize.fndtn.magellan', self.throttle(this.set_expedition_position.bind(this), settings.throttle_delay));
        },

        check_for_arrivals: function () {
            var self = this;
            self.update_arrivals();
            self.update_expedition_positions();
        },

        set_expedition_position: function () {
            var self = this;
            $('[' + this.attr_name() + '=fixed]', self.scope).each(function (idx, el) {
                var expedition = $(this),
                    settings = expedition.data('magellan-expedition-init'),
                    styles = expedition.attr('styles'), // save styles
                    top_offset, fixed_top;

                expedition.attr('style', '');
                top_offset = expedition.offset().top + settings.threshold;

                //set fixed-top by attribute
                fixed_top = parseInt(expedition.data('magellan-fixed-top'));
                if (!isNaN(fixed_top))
                    self.settings.fixed_top = fixed_top;

                expedition.data(self.data_attr('magellan-top-offset'), top_offset);
                expedition.attr('style', styles);
            });
        },

        update_expedition_positions: function () {
            var self = this,
                window_top_offset = $(window).scrollTop();

            $('[' + this.attr_name() + '=fixed]', self.scope).each(function () {
                var expedition = $(this),
                    settings = expedition.data('magellan-expedition-init'),
                    styles = expedition.attr('style'), // save styles
                    top_offset = expedition.data('magellan-top-offset');

                //scroll to the top distance
                if (window_top_offset + self.settings.fixed_top >= top_offset) {
                    // Placeholder allows height calculations to be consistent even when
                    // appearing to switch between fixed/non-fixed placement
                    var placeholder = expedition.prev('[' + self.add_namespace('data-magellan-expedition-clone') + ']');
                    if (placeholder.length === 0) {
                        placeholder = expedition.clone();
                        placeholder.removeAttr(self.attr_name());
                        placeholder.attr(self.add_namespace('data-magellan-expedition-clone'), '');
                        expedition.before(placeholder);
                    }
                    expedition.css({position: 'fixed', top: settings.fixed_top}).addClass('fixed');
                } else {
                    expedition.prev('[' + self.add_namespace('data-magellan-expedition-clone') + ']').remove();
                    expedition.attr('style', styles).css('position', '').css('top', '').removeClass('fixed');
                }
            });
        },

        update_arrivals: function () {
            var self = this,
                window_top_offset = $(window).scrollTop();

            $('[' + this.attr_name() + ']', self.scope).each(function () {
                var expedition = $(this),
                    settings = expedition.data(self.attr_name(true) + '-init'),
                    offsets = self.offsets(expedition, window_top_offset),
                    arrivals = expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']'),
                    active_item = false;
                offsets.each(function (idx, item) {
                    if (item.viewport_offset >= item.top_offset) {
                        var arrivals = expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']');
                        arrivals.not(item.arrival).removeClass(settings.active_class);
                        item.arrival.addClass(settings.active_class);
                        active_item = true;
                        return true;
                    }
                });

                if (!active_item) arrivals.removeClass(settings.active_class);
            });
        },

        offsets: function (expedition, window_offset) {
            var self = this,
                settings = expedition.data(self.attr_name(true) + '-init'),
                viewport_offset = window_offset;

            return expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']').map(function (idx, el) {
                var name = $(this).data(self.data_attr('magellan-arrival')),
                    dest = $('[' + self.add_namespace('data-magellan-destination') + '=' + name + ']');
                if (dest.length > 0) {
                    var top_offset = dest.offset().top - settings.destination_threshold;
                    if (settings.offset_by_height) {
                        top_offset = top_offset - expedition.outerHeight();
                    }
                    top_offset = Math.floor(top_offset);
                    return {
                        destination: dest,
                        arrival: $(this),
                        top_offset: top_offset,
                        viewport_offset: viewport_offset
                    }
                }
            }).sort(function (a, b) {
                if (a.top_offset < b.top_offset) return -1;
                if (a.top_offset > b.top_offset) return 1;
                return 0;
            });
        },

        data_attr: function (str) {
            if (this.namespace.length > 0) {
                return this.namespace + '-' + str;
            }

            return str;
        },

        off: function () {
            this.S(this.scope).off('.magellan');
            this.S(window).off('.magellan');
        },

        reflow: function () {
            var self = this;
            // remove placeholder expeditions used for height calculation purposes
            $('[' + self.add_namespace('data-magellan-expedition-clone') + ']', self.scope).remove();
        }
    };
}(jQuery, window, window.document));
