import * as tslib_1 from "tslib";
import { Component, Input, Output, EventEmitter, ContentChildren, QueryList, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, ViewChildren } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { InputBoxComponent } from './box';
import { uuid as getUUID } from '../util/uuid';
import { OnChange } from '../core/decorators';
/*
 * Provider Expression that allows component to register as a ControlValueAccessor.
 * This allows it to support [(ngModel)].
 * @docs-private
 */
var BOXGROUP_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(function () { return BoxGroupComponent; }),
    multi: true
};
/**
 * Box Group Component
 */
var BoxGroupComponent = /** @class */ (function () {
    function BoxGroupComponent(_cd) {
        var _this = this;
        this._cd = _cd;
        /**
         * when box group value change, emit a change event with the `BoxGroupValue`, which contains
         * the `currentValue` and `value` property
         */
        this.change = new EventEmitter();
        /**
         * box group type, either 'checkbox' or 'radio'
         * @default checkbox
         */
        this.type = 'checkbox';
        /**
         * Whether the box group is disabled
         * @default false
         */
        this.disabled = false;
        /**
         * @docs-private
         */
        this.disabledChange = new EventEmitter();
        /**
         * the unique name of the box group
         * @docs-private
         */
        this.uuid = getUUID();
        // listen to disabled property, and update sub child disabled state
        this.disabledChange.subscribe(function (disabled) {
            var boxList = _this._getBoxList();
            if (boxList) {
                boxList.forEach(function (box) {
                    box.disabled = disabled;
                });
            }
        });
    }
    BoxGroupComponent.prototype.ngOnInit = function () {
    };
    /**
     * select some value, according to the type, change sub box component behavior
     *
     * @param {any} value - box value
     * @docs-private
     */
    BoxGroupComponent.prototype.select = function (value) {
        var boxList = this._getBoxList();
        if (!boxList) {
            return;
        }
        if (this.type === 'radio') {
            boxList.forEach(function (item) {
                item.checked = (item.value + '') === (value + '');
            });
            this.value = [value];
            this.change.emit({
                currentValue: value,
                value: this.value
            });
        }
        else if (this.type === 'checkbox') {
            var box = boxList.find(function (v) { return (v.value + '') === (value + ''); });
            // de-duplicate value items
            var valueSet = new Set(this.value);
            if (box) {
                box.checked = !box.checked;
                box.checked ? valueSet.add(value) : valueSet.delete(value);
                this.value = Array.from(valueSet);
                this.change.emit({
                    currentValue: value,
                    value: this.value
                });
            }
        }
        this._cd.markForCheck();
        this._updateFormModel();
    };
    /**
     * Registers a callback that will be triggered when the value has changed.
     * Implemented as part of ControlValueAccessor.
     * @param fn On change callback function.
     */
    BoxGroupComponent.prototype.registerOnChange = function (fn) {
        this._onModelChange = fn;
    };
    /**
     * Registers a callback that will be triggered when the control has been touched.
     * Implemented as part of ControlValueAccessor.
     * @param fn On touch callback function.
     */
    BoxGroupComponent.prototype.registerOnTouched = function (fn) {
        this._onTouch = fn;
    };
    /**
     * Sets the model value. Implemented as part of ControlValueAccessor.
     * @param value Value to be set to the model. It must be an array.
     */
    BoxGroupComponent.prototype.writeValue = function (value) {
        if (value && !Array.isArray(value)) {
            throw new Error('使用表单赋值时，box-group 的值必须传入数组形式，即使单选框也一样');
        }
        if (value) {
            this.value = value;
            // when init, set children toggle button state
            this._forceUpdateValue(value);
        }
    };
    /**
     * force update box group value
     *
     * @param {any[]} value
     * @returns
     */
    BoxGroupComponent.prototype._forceUpdateValue = function (value) {
        var boxList = this._getBoxList();
        if (!boxList) {
            return;
        }
        if (this.type === 'radio') {
            boxList.forEach(function (item) {
                item.checked = (item.value + '') === (value + '');
            });
        }
        else if (this.type === 'checkbox') {
            value = value.map(function (v) { return v + ''; });
            boxList.forEach(function (v) { return v.checked = value.includes(v.value + ''); });
        }
        // emit change value
        // checkbox's current value is the last value in the array, and radiobox's current value is
        // the value
        var currentValue = Array.isArray(value) && value.length ? value[value.length - 1] : '';
        this.change.emit({
            currentValue: currentValue,
            value: this.value
        });
        this._cd.markForCheck();
    };
    /**
     * Toggles the disabled state of the component. Implemented as part of ControlValueAccessor.
     * @param isDisabled Whether the component should be disabled.
     */
    BoxGroupComponent.prototype.setDisabledState = function (isDisabled) {
        this.disabled = isDisabled;
    };
    /**
     * update form model value and mark for check
     */
    BoxGroupComponent.prototype._updateFormModel = function () {
        if (this._onModelChange) {
            this._onModelChange(this.value);
        }
        if (this._onTouch) {
            this._onTouch(this.value);
        }
    };
    BoxGroupComponent.prototype._getBoxList = function () {
        var hasDatasource = this.datasource && this.datasource.length;
        return hasDatasource ? this._viewBoxList : this._contentBoxList;
    };
    /**
     * reset box group value
     */
    BoxGroupComponent.prototype.reset = function () {
        this._getBoxList().forEach(function (box) {
            box.checked = false;
        });
        this.value = [];
    };
    tslib_1.__decorate([
        Output(),
        tslib_1.__metadata("design:type", EventEmitter)
    ], BoxGroupComponent.prototype, "change", void 0);
    tslib_1.__decorate([
        OnChange(),
        Input(),
        tslib_1.__metadata("design:type", String)
    ], BoxGroupComponent.prototype, "type", void 0);
    tslib_1.__decorate([
        OnChange(true),
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], BoxGroupComponent.prototype, "disabled", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Array)
    ], BoxGroupComponent.prototype, "datasource", void 0);
    tslib_1.__decorate([
        OnChange(),
        Input(),
        tslib_1.__metadata("design:type", Object)
    ], BoxGroupComponent.prototype, "value", void 0);
    tslib_1.__decorate([
        OnChange(),
        Input(),
        tslib_1.__metadata("design:type", String)
    ], BoxGroupComponent.prototype, "uuid", void 0);
    tslib_1.__decorate([
        ContentChildren(forwardRef(function () { return InputBoxComponent; })),
        tslib_1.__metadata("design:type", QueryList)
    ], BoxGroupComponent.prototype, "_contentBoxList", void 0);
    tslib_1.__decorate([
        ViewChildren(forwardRef(function () { return InputBoxComponent; })),
        tslib_1.__metadata("design:type", QueryList)
    ], BoxGroupComponent.prototype, "_viewBoxList", void 0);
    BoxGroupComponent = tslib_1.__decorate([
        Component({
            selector: 'nb-boxgroup',
            template: "<ng-container *ngIf=\"datasource && datasource.length\"><nb-checkbox *ngFor=\"let d of datasource\" [value]=\"d.value\" [checked]=\"d.checked\" [disabled]=\"d.disabled\" [type]=\"type\">{{ d.text }}</nb-checkbox></ng-container><ng-container *ngIf=\"!datasource\"><ng-content></ng-content></ng-container>",
            encapsulation: ViewEncapsulation.None,
            changeDetection: ChangeDetectionStrategy.OnPush,
            preserveWhitespaces: false,
            providers: [BOXGROUP_VALUE_ACCESSOR],
            host: {
                'class': 'nb-widget nb-boxgroup',
                '[class.nb-boxgroup-disabled]': 'disabled'
            },
            exportAs: 'nbBoxGroup'
        }),
        tslib_1.__metadata("design:paramtypes", [ChangeDetectorRef])
    ], BoxGroupComponent);
    return BoxGroupComponent;
}());
export { BoxGroupComponent };
//# sourceMappingURL=box-group.js.map