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

    // PLUGIN CLASS
    // ============
    const ItemLimitPlugin = {

        currentViewport: null,
        limits: null,
        wrapperSelector: '.et-item-limit-wrapper',
        itemSelector: '.et-item-limit-item',
        moreSelector: '.et-item-limit-more',
        $wrappers: [],

        /**
         * @this {PluginBase & ItemLimitPlugin}
         * @param {HTMLElement} element
         * @param {Object} options
         */
        init: function (element, options) {
            this.limits = this.$el.data('item-limit');
            if(!this.limits) {
                // Limit data is missing, abort
                return;
            }
            this.wrapperSelector = this.$el.data('item-limit-wrapper') ?? this.wrapperSelector;
            this.itemSelector = this.$el.data('item-limit-item') ?? this.itemSelector; // The item selector must be *relative* to the wrapper, i.e. it will be used with .find() on the wrapper itself
            this.moreSelector = this.$el.data('item-limit-more') ?? this.moreSelector; // The "more" trigger selector must be *relative* to the wrapper, i.e. it will be ussed with .find() on the wrapper itself
            this.$wrappers = this.$el.find(this.wrapperSelector);
            if(!this.$wrappers.length) {
                // No wrappers available, do nothing
                return;
            }

            this.currentViewport = this.getCurrentViewport();
            this.hideItems();
            this.registerEvents();

            $(window).on('resize', () => {
                let viewportBefore = this.currentViewport;
                this.currentViewport = this.getCurrentViewport();
                if(viewportBefore !== this.currentViewport) {
                    // Viewport changed
                    this.hideItems();
                    this.registerEvents();
                }
            });
        },

        getCurrentViewport: function() {
            return viewport.current();
        },

        registerEvents: function() {
            // Register for clicks on the trigger elements *for each* wrapper
            for (let $wrapper of this.$wrappers) {
                $wrapper = $($wrapper);
                $wrapper.find(this.moreSelector).off('click.et').on('click.et', (e) => {
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    this.showItems($wrapper);
                });
            }
            this.Events.publish('easytemplate/Plugin/etItemLimitPlugin/onRegisterEvents', [this]);
        },

        hideItems: function() {
            // For each wrapper, hide the items that should be hidden according to this.limits[viewport].
            let limit = this.limits[this.getCurrentViewport()];
            for (let $wrapper of this.$wrappers) {
                $wrapper = $($wrapper);
                $wrapper.find(this.itemSelector).show();
                this.hideTrigger($wrapper);
                if(limit && limit > 0) {
                    let $wrapperItems = $wrapper.find(this.itemSelector);
                    if($wrapperItems.length > (limit + 1)) {
                        // Only hide items if there is at least 2 more items than the limit to prevent unnecessary clicks
                        $wrapperItems.eq(limit - 1).nextAll().addClass('et-item-limit-hidden').hide();
                        this.showTrigger($wrapper);
                    }
                }
            }
            this.Events.publish(
                'easytemplate/Plugin/etItemLimitPlugin/onHideItems',
                [this]
            );
        },
        showItems: function($wrapper) {
            $wrapper.find(this.itemSelector).removeClass('et-item-limit-hidden').show();
            this.Events.publish('easytemplate/Plugin/etItemLimitPlugin/onShowItems', [this, $wrapper]);
            this.hideTrigger($wrapper);
        },
        hideTrigger: function($wrapper) {
            $wrapper.find(this.moreSelector).hide();
            this.Events.publish('easytemplate/Plugin/etItemLimitPlugin/onHideTrigger', [this, $wrapper]);
        },
        showTrigger: function($wrapper) {
            if($wrapper.find(this.itemSelector).filter('.et-item-limit-hidden').length) {
                $wrapper.find(this.moreSelector).removeClass('et-item-limit-hidden').show();
                this.Events.publish('easytemplate/Plugin/etItemLimitPlugin/onShowTrigger', [this, $wrapper]);
            }
        }
    };

    // REGISTER AND ADD THE PLUGIN
    // ===========================
    if (!window.easytemplate && !window.easytemplate.PluginManager) {
        throw Error('Cannot initialize Easytemplate Plugin. plugin-manager.js has to be loaded first!');
    }

    /** @type {PluginManager} manager */
    const manager = window.easytemplate.PluginManager;
    manager.addPlugin('[data-item-limit]', ItemLimitPlugin, 'etItemLimitPlugin');
    // Force plugin manager to re-initialize us on variation or content load
    $(window).on('article-variation-loaded.et evo:loaded.evo.content', function () {
        manager.reinitialize('etItemLimitPlugin');
    });
})(jQuery, document, window, ResponsiveBootstrapToolkit);