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

    // PLUGIN CLASS
    // ============
    const EndlessScrollPluginClass = {

        element: null,
        direction: 'forward', // vs. 'back'
        initialPage: 0,
        maxPage: 0,
        currentPage: 0,
        autoLoadCount: 0,
        currentAutoLoads: 0,
        intersectionObserver: null,
        moreLink: null,
        moreTriggerSelector: '.et-endless-scroll-more-trigger',
        $moreTrigger: null,
        loadingIndicatorSelector: '.et-endless-scroll-loading-indicator',
        $loadingIndicator: null,
        productListSelector: '.product-list',
        $productList: null,
        productSelector: '.product-list .product-wrapper',

        /**
         * @this {PluginBase & EndlessScrollPluginClass}
         * @param {HTMLElement} element
         * @param {Object} options
         */
        init: function (element, options) {
            if (this.$el.hasClass('et-endless-scroll-initialized')) {
                return; // prevent double initialization
            }

            this.element = element;
            this.initialPage = this.getCurrentPage(this.$el);
            this.currentPage = this.initialPage;
            this.maxPage = this.getMaxPage(this.$el);
            this.direction = this.getDirection(this.$el);
            this.moreLink = this.getMoreLink(this.$el);
            this.autoLoadCount = this.getAutoLoadCount(this.$el);
            this.$moreTrigger = this.$el.find(this.moreTriggerSelector);
            this.$productList = $(this.productListSelector);
            this.$loadingIndicator = this.$el.find(this.loadingIndicatorSelector);

            this.Events.publish('easytemplate/Plugin/etEndlessScroll/init', [this]);

            this.updateMoreTrigger();
            this.registerTriggerAction();
            this.$el.addClass('et-endless-scroll-initialized');
        },
        getCurrentPage: function ($element) {
            return $element.data('et-endless-scroll-current');
        },
        getMaxPage: function ($element) {
            return $element.data('et-endless-scroll-max');
        },
        getMoreLink: function ($element) {
            if (this.direction === 'forward') {
                return $element.data('et-endless-scroll-next');
            } else {
                return $element.data('et-endless-scroll-prev');
            }
        },
        getAutoLoadCount: function ($element) {
            return $element.data('et-endless-scroll-auto-load-count');
        },
        getDirection: function ($element) {
            return $element.data('et-endless-scroll-direction');
        },
        registerTriggerAction: function () {
            this.$moreTrigger.off('.etEndlessScroll');
            this.$moreTrigger.on('click.etEndlessScroll', () => {
                if (this.moreLink !== null) {
                    // Load next link data via XHR
                    this.loadMorePageContent();
                }
            });

            this.Events.publish('easytemplate/Plugin/etEndlessScroll/onRegisterTriggerAction', [this]);
        },
        setLoading: function (isLoading) {
            if (this.$loadingIndicator === null) {
                return;
            }
            if (isLoading) {
                this.$loadingIndicator.css({display: 'flex'});
            } else {
                this.$loadingIndicator.css({display: 'none'});
            }

            this.Events.publish('easytemplate/Plugin/etEndlessScroll/onSetLoading', [this, { isLoading }]);
        },
        loadMorePageContent: function () {
            let url = this.moreLink;
            history.pushState(null, null, this.moreLink);
            let ajaxOptions = {data: 'isAjax'};
            $.evo.trigger('load.evo.content', {url: url});
            this.setLoading(true);
            this.$moreTrigger.prop('disabled', true);

            this.Events.publish('easytemplate/Plugin/etEndlessScroll/onLoadMorePageContent', [this, { url, ajaxOptions }]);

            $.ajax(url, ajaxOptions).done((html) => {
                let $data = $(html);
                if (typeof $.evo.extended === 'function') {
                    $.evo.extended().register();
                }
                if (typeof $.evo.article === 'function') {
                    $.evo.article().register($data);
                }
                // Add products to the product list
                let $products = $data.find(this.productSelector);
                if (this.direction === 'forward') {
                    $products.appendTo(this.$productList);
                } else {
                    $products.prependTo(this.$productList);
                }
                // update this.moreLink
                let $endlessScrollElement = $data.find('[data-et-endless-scroll]');
                this.moreLink = this.getMoreLink($endlessScrollElement);

                this.Events.publish('easytemplate/Plugin/etEndlessScroll/onLoadMorePageContentResponse', [this, { response: $data}]);
            })
                .always(() => {
                    $.evo.trigger('contentLoaded'); // compatibility
                    $.evo.trigger('loaded.evo.content', {url: url});
                    this.$moreTrigger.prop('disabled', false);
                    this.updateMoreTrigger();
                    this.setLoading(false);

                    this.Events.publish('easytemplate/Plugin/etEndlessScroll/onLoadMorePageContentFinished', [this]);
                });
        },
        initIntersectionObserver: function() {
            if (this.$moreTrigger.length && this.direction === 'forward' && this.autoLoadCount > 0 && 'IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'isIntersecting' in window.IntersectionObserverEntry.prototype) {
                this.intersectionObserver = new IntersectionObserver(
                    (entries, observer) => {
                        if(entries.length && this.currentAutoLoads < this.autoLoadCount) {
                            let entry = entries[0];
                            if (entry.isIntersecting) {
                                this.currentAutoLoads = this.currentAutoLoads + 1;
                                this.loadMorePageContent();
                            }
                        }
                    }, {
                        root: null,
                        rootMargin: '0px',
                        threshold: 0
                    });
                this.intersectionObserver.observe(this.$moreTrigger.get(0));

                this.Events.publish('easytemplate/Plugin/etEndlessScroll/onInitIntersectionObserver', [this]);
            }
        },
        updateMoreTrigger: function () {
            if (this.moreLink === '' || this.moreLink === null || this.moreLink === undefined) {
                if (this.intersectionObserver !== null) {
                    this.intersectionObserver.unobserve(this.$moreTrigger.get(0));
                    this.intersectionObserver = null;
                }
                this.$moreTrigger.hide();

                this.Events.publish('easytemplate/Plugin/etEndlessScroll/onUpdateMoreTrigger', [this, {show: false}]);
            } else {
                if(this.intersectionObserver === null) {
                    this.initIntersectionObserver();
                }
                this.$moreTrigger.show();

                this.Events.publish('easytemplate/Plugin/etEndlessScroll/onUpdateMoreTrigger', [this, {show: true}]);
            }
        }
    };

    // 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-et-endless-scroll]', EndlessScrollPluginClass, 'etEndlessScrollPlugin');
})(jQuery, document, window, ResponsiveBootstrapToolkit);