/**
 * Design (display mode) selector rendered as small clickable preview cards.
 *
 * Wraps a hidden input and writes the selected value back into it, so it works
 * both programmatically (new DesignSelect({...}).inject(node)) and as a
 * settings control via data-qui over a conf-bound input.
 *
 * Options:
 *   value      {String}  currently selected design
 *   designs    {Array}   design keys to offer (default: all)
 *   allowEmpty {Boolean} add a leading "default (project setting)" card whose
 *                        value is an empty string
 *
 * @module package/quiqqer/info-popup/bin/controls/DesignSelect
 * @author www.pcsg.de
 */
define('package/quiqqer/info-popup/bin/controls/DesignSelect', [

    'qui/controls/Control',
    'Locale',

    'css!package/quiqqer/info-popup/bin/controls/DesignSelect.css'

], function (QUIControl, QUILocale) {
    "use strict";

    const lg = 'quiqqer/info-popup';

    const ALL_DESIGNS = ['content', 'sidebar', 'sidebarRight', 'top'];
    const MEDIA_DESIGNS = ['sidebar', 'sidebarRight', 'top'];

    return new Class({

        Extends: QUIControl,
        Type: 'package/quiqqer/info-popup/bin/controls/DesignSelect',

        Binds: [
            '$onImport',
            '$onDestroy'
        ],

        options: {
            value: '',
            designs: ALL_DESIGNS,
            allowEmpty: false
        },

        initialize: function (options) {
            this.parent(options);

            this.$Input = null;
            this.$Grid = null;

            this.addEvents({
                onImport: this.$onImport,
                onDestroy: this.$onDestroy
            });
        },

        /**
         * Programmatic usage: build a wrapper with an own hidden input.
         *
         * @return {HTMLElement}
         */
        create: function () {
            this.$Elm = new Element('div', {
                'class': 'quiqqer-info-popup-designSelect-control'
            });

            this.$Input = new Element('input', {
                type: 'hidden',
                value: this.getAttribute('value') || ''
            }).inject(this.$Elm);

            this.$buildGrid();

            return this.$Elm;
        },

        /**
         * Settings usage: import over the conf-bound input and render the cards
         * next to it (the input stays as the value carrier).
         */
        $onImport: function () {
            this.$Input = this.getElm();
            this.$Input.type = 'hidden';

            this.$Elm = new Element('div', {
                'class': 'quiqqer-info-popup-designSelect-control field-container-field'
            }).wraps(this.$Input);

            this.$buildGrid();
        },

        $onDestroy: function () {
            if (this.$Input) {
                this.$Input.setStyle('display', null);
            }
        },

        /**
         * Render the card grid for the configured designs.
         */
        $buildGrid: function () {
            this.$Grid = new Element('div', {
                'class': 'quiqqer-info-popup-designSelect'
            }).inject(this.$Elm);

            this.$getDesigns().forEach((design) => {
                this.$renderCard(design);
            });

            this.$refresh();
        },

        /**
         * The list of designs to render, optionally prefixed with the empty
         * "default" entry.
         *
         * @return {Array}
         */
        $getDesigns: function () {
            let designs = (this.getAttribute('designs') || ALL_DESIGNS).filter((design) => {
                return ALL_DESIGNS.indexOf(design) !== -1;
            });

            if (this.getAttribute('allowEmpty')) {
                designs = [''].concat(designs);
            }

            return designs;
        },

        /**
         * Render a single design card.
         *
         * @param {String} design
         */
        $renderCard: function (design) {
            const title = design === ''
                ? QUILocale.get(lg, 'displayMode.default')
                : QUILocale.get(lg, 'displayMode.' + design);

            const Card = new Element('button', {
                'class': 'quiqqer-info-popup-designSelect-card',
                type: 'button',
                'data-design': design,
                'aria-pressed': 'false',
                events: {
                    click: () => {
                        this.setValue(design);
                    },
                    keydown: (event) => {
                        if (event.key === 'Enter' || event.key === ' ') {
                            event.preventDefault();
                            this.setValue(design);
                        }
                    }
                }
            }).inject(this.$Grid);

            new Element('div', {
                'class': 'quiqqer-info-popup-designSelect-preview'
            }).adopt(this.$previewNode(design)).inject(Card);

            new Element('div', {
                'class': 'quiqqer-info-popup-designSelect-title',
                text: title
            }).inject(Card);
        },

        /**
         * Build the small skeleton preview for a design ('' = default card).
         *
         * @param {String} design
         * @return {HTMLElement}
         */
        $previewNode: function (design) {
            if (design === '') {
                const Default = new Element('div', {
                    'class': 'quiqqer-info-popup-designSelect-skeleton is-default'
                });

                new Element('div', {
                    'class': 'quiqqer-info-popup-designSelect-defaultBox'
                }).inject(Default);

                return Default;
            }

            const Preview = new Element('div', {
                'class': 'quiqqer-info-popup-designSelect-skeleton is-' + design
            });

            if (MEDIA_DESIGNS.indexOf(design) !== -1) {
                new Element('div', {
                    'class': 'quiqqer-info-popup-designSelect-media'
                }).inject(Preview);
            }

            const Body = new Element('div', {
                'class': 'quiqqer-info-popup-designSelect-body'
            }).inject(Preview);

            ['is-title', '', 'is-short'].forEach((modifier) => {
                new Element('div', {
                    'class': ('quiqqer-info-popup-designSelect-line ' + modifier).trim()
                }).inject(Body);
            });

            return Preview;
        },

        /**
         * Highlight the active card.
         */
        $refresh: function () {
            if (!this.$Grid) {
                return;
            }

            const value = this.getValue();

            this.$Grid.getElements('.quiqqer-info-popup-designSelect-card').each(function (Card) {
                const isActive = Card.get('data-design') === value;

                Card.set('aria-pressed', isActive ? 'true' : 'false');

                if (isActive) {
                    Card.addClass('is-active');
                    return;
                }

                Card.removeClass('is-active');
            });
        },

        /**
         * @return {String}
         */
        getValue: function () {
            return this.$Input ? (this.$Input.value || '') : '';
        },

        /**
         * @param {String} value
         */
        setValue: function (value) {
            if (!this.$Input) {
                return;
            }

            this.$Input.value = value;
            this.$refresh();
            this.fireEvent('change', [value, this]);
        }
    });
});
