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

    // PLUGIN CLASS
    // ============
    /**
     * @typedef {{
     *      maxHeight: {
     *          xs: Number,
     *          sm: Number,
     *          md: Number,
     *          lg: Number,
     *          xl: Number
     *      },
     *      animationSpeed: Number,
     *      triggerMore: String,
     *      triggerLess: String
     *      textContainer: String
     * }} ShortenToPlugin.Options
     */
    const ShortenToPlugin = {
        /** @type {ShortenToPlugin.Options} */
        DEFAULTS: {
            "maxHeight": {
                "xs": 0,
                "sm": 0,
                "md": 0,
                "lg": 0,
                "xl": 0
            },
            // Selector to element which contains the trigger buttons (gets overwritten by `data-shorten-to-trigger`)
            "triggerMore": ".et-shorten-to-more",
            "triggerLess": ".et-shorten-to-less",

            // Selector to the text container (gets overwritten by `data-shorten-to-text-container`)
            "textContainer": ".et-shorten-to-text",

            // Speed of animation in ms (gets overwritten by `data-shorten-to-speed`)
            "animationSpeed": 500,

            // Switch to disable animation and just set height to auto
            "autoHeight": false
        },

        /**
         * @type {ShortenToPlugin.Options}
         */
        options: null,

        /** @type {HTMLElement} */
        element: null,

        /** @type {Number} */
        initialHeight: 0,

        /** @type {String} */
        initialColumns: 'auto',

        /** @type {JQuery<HTMLElement>} */
        $textContainer: null,

        /** @type {JQuery<HTMLElement>} */
        $triggerMore: null,


        /** @type {JQuery<HTMLElement>} */
        $triggerLess: null,

        autoHeight: false,

        /**
         * @this {PluginBase & ShortenToPlugin}
         * @param {HTMLElement} element
         * @param {Object} options
         * @public
         */
        init: function(element, options) {
            this.element = element;

            this.options = $.extend(this.options, {
                "maxHeight": this.$el.data('shorten-to'),
                "textContainer": this.$el.data('shorten-to-text'),
                "triggerMore": this.$el.data('shorten-to-more'),
                "triggerLess": this.$el.data('shorten-to-less'),
                "animationSpeed": this.$el.data('shorten-to-speed'),
                "autoHeight": this.$el.data('shorten-to-height-auto')
            });

            this.$triggerMore = this.$el.parent().find(this.options.triggerMore).first();
            if(!this.$triggerMore.length) {
                return;
            }
            this.$triggerLess = this.$el.parent().find(this.options.triggerLess).first();

            this.autoHeight = this.options.autoHeight ?? this.DEFAULTS.autoHeight;

            // Get Elements and set classes
            let $targetContainer =  this.$el.parent().find(this.options.textContainer).first();
            if($targetContainer.length) {
                this.$textContainer = $targetContainer;
            } else {
                this.$textContainer = this.$el;
            }

            // Check if text container was initialized before - if so, do nothing.
            if(this.$textContainer.hasClass('initialized')) {
                return;
            }
            this.$textContainer.addClass('et-shorten-to-text');

            this.setHeight();
        },

        /**
         * Set the maximum height if needed and register events.
         * @this {PluginBase & ShortenToPlugin}
         */
        setHeight: function() {
            const maxHeight =  parseInt(this.options.maxHeight[viewport.current()]) || 0;
            this.$textContainer.addClass('initializing'); // we set this class to disable inline styles that may have been set to prevent CLS
            this.initialHeight = this.$textContainer.outerHeight();
            this.initialColumns = this.$textContainer.css('column-count');

            if (maxHeight > 0 && this.initialHeight > maxHeight) {
                this.$textContainer.css({ columnCount: 1});
                this.$textContainer.css('height', maxHeight);
                this.$el.addClass('et-shorten-to-collapsed');
                this.$triggerMore.attr('aria-expanded', false);
                this.$triggerMore.show();
                this.$triggerLess.attr('aria-expanded', false);
                this.$triggerLess.hide();
                this.registerEvents();
            }
            this.$textContainer.addClass('initialized').removeClass('initializing');
            this.Events.publish('easytemplate/Plugin/etShortenToPlugin/onSetHeight', [this, {maxHeight}]);
        },

        /**
         * Register the trigger events to collapse the shortened text
         * @this {PluginBase & ShortenToPlugin}
         */
        registerEvents: function() {
            const self = this;
            const maxHeight = parseInt(this.options.maxHeight[viewport.current()]) || 0;

            this.$triggerMore.on('click', function(event) {
                event.preventDefault();
                self.$textContainer.css({ columnCount: self.initialColumns});
                // Text is NOT expanded -> expand text to full height
                if(self.autoHeight) {
                    // just set to height auto if auto height is enabled
                    self.$textContainer.css({
                       height: 'auto'
                    });
                } else {
                    self.$textContainer.animate({
                        height: self.initialHeight + 'px'
                    }, self.options.animationSpeed, function() {
                        // Make sure that the container does show everything, just in case the initial height computation was wrong. (May result from font swapping.)
                        self.$textContainer.css({
                            height: 'auto'
                        });
                    });
                }
                self.$el.removeClass('et-shorten-to-collapsed');
                self.$triggerMore.attr('aria-expanded', 'true');
                self.$triggerMore.hide();
                self.$triggerLess.attr('aria-expanded', 'true');
                self.$triggerLess.show();
            });

            this.$triggerLess.on('click', function (event) {
                event.preventDefault();
                self.$textContainer.css({ columnCount: 1});
                // Text is expanded -> close to max height
                if(self.autoHeight) {
                    self.$textContainer.css({
                        height: maxHeight + 'px'
                    });
                } else {
                    self.$textContainer.animate({
                        height: maxHeight + 'px'
                    }, self.options.animationSpeed);
                }
                self.$el.addClass('et-shorten-to-collapsed');
                self.$triggerMore.attr('aria-expanded', 'false');
                self.$triggerMore.show();
                self.$triggerLess.attr('aria-expanded', 'false');
                self.$triggerLess.hide();
            });

            this.Events.publish('easytemplate/Plugin/etShortenToPlugin/onRegisterEvents', [this, {maxHeight}]);
        }
    };

    // 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-shorten-to]', ShortenToPlugin, 'etShortenToPlugin');
    // Force plugin manager to re-initialize us on variation load
    $(window).on('article-variation-loaded.et evo:loaded.evo.content', function () {
        manager.reinitialize('etShortenToPlugin');
    });
})(jQuery, document, window, ResponsiveBootstrapToolkit);