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

    // PLUGIN CLASS
    // ============
    const InfoBoxPlugin = {

        DISPLAY_MODE_ROW: 'row',
        DISPLAY_MODE_BOX: 'box',
        $boxes: null,
        $productList: null,
        currentViewport: null,

        /**
         * @this {PluginBase & InfoBoxPlugin}
         * @param {HTMLElement} element
         * @param {Object} options
         */
        init: function (element, options) {
            this.$productList = this.$el.find('.product-list');
            this.$boxes = this.$el.find('.et-info-box');
            if(this.$productList.length && this.$boxes.length) {
                this.currentViewport = this.getCurrentViewport();
                this.$boxes.detach();
                this.positionBoxes(false);
                this.$el.addClass('et-info-boxes-initialized');
            }
            $(window).on('resize', () => {
                let viewportBefore = this.currentViewport;
                this.currentViewport = this.getCurrentViewport();
                if(viewportBefore !== this.currentViewport) {
                    this.positionBoxes(true);
                }
            });
        },

        positionBoxes: function(rowsOnly) {
            if(!rowsOnly) {
                this.$productList.find('.et-info-box').remove(); // remove info boxes from the dom within the product list (e.g. from a previous insertion)
                // position box-boxes first
                this.$boxes.filter('[data-display-mode="box"]').each((index, element) => {
                    let $box = $(element);
                    let targetPositionData = $box.data('target-position');
                    if (targetPositionData) {
                        let targetPosition = targetPositionData[this.currentViewport];
                        if (typeof targetPosition === 'string') {
                            targetPosition = parseInt(targetPosition);
                        }
                        if (isNaN(targetPosition)) {
                            return;
                        }
                        this.positionBoxInPosition($box.clone(), targetPosition);
                    }
                });
            } else {
                this.$productList.find('.et-info-box[data-display-mode="row"]').remove();
            }
            // position row-boxes last
            this.$boxes.filter('[data-display-mode="row"]').each((index, element) => {
                let $box = $(element);
                let targetPositionData = $box.data('target-position');
                if(targetPositionData) {
                    let targetPosition = targetPositionData[this.currentViewport];
                    if(typeof targetPosition !== 'number') {
                        targetPosition = parseInt(targetPosition);
                    }
                    if(isNaN(targetPosition)) {
                        return;
                    }
                    this.positionBoxInRow($box.clone(), targetPosition);
                }
            })

            this.Events.publish('easytemplate/Plugin/etInfoBoxPlugin/onPositionBoxes', [this, {rowsOnly}]);
        },
        getCurrentViewport: function() {
            return viewport.current();
        },
        positionBoxInPosition($box, targetPosition) {
            let $existingBoxes = this.$productList.find('.product-wrapper.col, .et-info-box[data-display-mode="box"]');
            if(!$existingBoxes.length || !$existingBoxes.get(targetPosition - 1)) {
                this.$productList.append($box);
            } else {
                $($existingBoxes.get(targetPosition - 1)).before($box);
            }

            this.Events.publish(
                'easytemplate/Plugin/etInfoBoxPlugin/onPositionBoxInPosition',
                [this, {$box, targetPosition, $existingBoxes}]
            );
        },
        positionBoxInRow($box, targetRow) {
            if(this.$productList.data('products-per-row')) {
                let productsPerRow = this.$productList.data('products-per-row')[this.currentViewport];
                let $existingBoxes = this.$productList.find('.product-wrapper.col, .et-info-box[data-display-mode="box"]');
                let targetIndex = (targetRow - 1) * productsPerRow;
                if (!$existingBoxes.length || !$existingBoxes.get(targetIndex - 1)) {
                    this.$productList.append($box);
                } else {
                    $($existingBoxes.get(targetIndex - 1)).after($box);
                }

                this.Events.publish(
                    'easytemplate/Plugin/etInfoBoxPlugin/onPositionBoxInRow',
                    [this, {$box, targetRow, targetIndex, productsPerRow, $existingBoxes}]
                );
            }
        }
    };

    // 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('.et-product-list-products-wrapper', InfoBoxPlugin, 'etInfoBoxPlugin');

    // Re-Init on content load (i.e. pagination) if our productlist-wrapper is gone / needs to be re-adjusted
    $(document).on('evo:loaded.evo.content', () => {
        let $productListWrapper = $('.et-product-list-products-wrapper');
        if(!$productListWrapper.hasClass('et-info-boxes-initialized')) {
            manager.reinitialize('etInfoBoxPlugin');
        }
    });
})(jQuery, document, window, ResponsiveBootstrapToolkit);