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);

        if (!value)
            this.checkedDummyCount = null;
    }

    /**
     * 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;

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

    countRows() {
        if (!this.model || !this.model.data) return;

        const data = this.model.data;
        const params = {
            filter: {
                limit: null
            }
        };
        if (this.model.userFilter)
            Object.assign(params.filter, this.model.userFilter);
        if (this.model.userParams)
            Object.assign(params, this.model.userParams);

        this.rows = data.length;
        this.$http.get(this.model.url, {params})
            .then(res => {
                this.allRowsCount = res.data.length;
                this.allRowsText = this.$t('SelectAllRows', {
                    rows: this.allRowsCount
                });
            });
    }

    checkDummy() {
        if (this.checkedDummyCount)
            return this.checkedDummyCount = null;

        this.checkedDummyCount = this.allRowsCount;
    }

    isCheckedDummy() {
        return this.checked && this.checkDummyEnabled;
    }

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

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