import ngModule from '../../module';
import FormInput from '../form-input';
import './style.scss';

/**
 * Multicheck component for checking all form instances at once
 * @param {SmallInt} checkAll Primary input-check state: 0 -> uncheck, 1 -> checked
 * @param {Array} data List of options shown in drop-down
 * @param {Array} models Elements to check / unCheck
 */
export default class MultiCheck extends FormInput {
    constructor($element, $scope) {
        super($element, $scope);
        this.checkAll = false;
        this._checked = false;
        this.checkField = 'checked';
        this.isIntermediate = false;
        this.mayusEnabled = false;
        this.window.addEventListener('keydown', event => {
            if (event.key === 'Shift')
                this.mayusEnabled = true;
        });
        this.window.addEventListener('keyup', event => {
            if (event.key === 'Shift')
                this.mayusEnabled = false;
        });
        this.window.addEventListener('selectstart', event => {
            if (this.mayusEnabled)
                event.preventDefault();
        });
    }

    /**
     * Gets array model instance
     *
     * @return {ArrayModel} - Array model instance
     */
    get model() {
        return this._model;
    }

    /**
     * Sets the array model instance
     * Changes indeterminate property for
     * the check component
     *
     * @param {ArrayModel} value - Array model instance
     */
    set model(value) {
        this._model = value;

        if (value) {
            value.on('rowChange', row => {
                this.isIndeterminate = !this.areAllUnchecked() && !this.areAllChecked();

                if (this.mayusEnabled) {
                    this.currentSelection = row.obj.$orgIndex;

                    if (this.lastSelection != undefined && this.currentSelection != undefined)
                        this.setSelection(row.value, this.lastSelection, this.currentSelection);
                }

                this.lastSelection = row.obj.$orgIndex;

                if (this.areAllChecked())
                    this._checked = true;
                else if (!this.areAllChecked())
                    this._checked = false;
            });

            value.on('dataChange', () => {
                if (this.checked) this.toggle();
            });
        }
    }

    setSelection(value, from, to) {
        let start = from;
        let end = to;

        if (from > to) {
            start = to;
            end = from;
        }

        const data = this.model.data;
        for (let i = start; i <= end; i++)
            data[i].checked = value;
    }

    /**
     * Gets current check state
     */
    get checked() {
        return this._checked;
    }

    /**
     * Sets current check state
     *
     * @param {Boolean} value - Checkbox state [undefined, true, false]
     */
    set checked(value) {
        this._checked = value;
        this.checkAll = value;

        this.toggle();
        this.emit('change', value);
    }

    /**
     * Returns a bolean result for
     * checked instances
     *
     * @return {Boolean} - True if all instances are checked
     */
    areAllChecked() {
        if (!this.model || !this.model.data) return;

        const data = this.model.data;
        return data.every(item => {
            return item[this.checkField] === true;
        });
    }

    /**
     * Returns a bolean result for
     * checked instances
     *
     * @return {Boolean} - False if all instances are checked
     */
    areAllUnchecked() {
        if (!this.model || !this.model.data) return;

        const data = this.model.data;
        return data.every(item => {
            return item[this.checkField] === false;
        });
    }

    /**
     * Toggles checked property on
     * all instances
     */
    toggle() {
        const data = this.model.data;
        if (!data) return;
        data.forEach(el => {
            el[this.checkField] = this.checkAll;
        });
    }
}

ngModule.vnComponent('vnMultiCheck', {
    template: require('./multi-check.html'),
    controller: MultiCheck,
    bindings: {
        model: '<',
        checkField: '<?',
        checkAll: '=?',
        disabled: '<?'
    }
});