import * as tslib_1 from "tslib";
import { Component, Input, Output, ContentChildren, ViewChildren, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, QueryList, Optional, forwardRef, EventEmitter } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { OnChange } from '../core/decorators';
/*
 * Provider Expression that allows component to register as a ControlValueAccessor.
 * This allows it to support [(ngModel)].
 * @docs-private
 */
var BUTTONGROUP_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(function () { return ButtonGroupComponent; }),
    multi: true
};
/**
 * Button Group Component
 */
var ButtonGroupComponent = /** @class */ (function () {
    function ButtonGroupComponent(_cd) {
        this._cd = _cd;
        /**
         * button group change event, emit the `ButtonGroupValue`
         * , which with the `currentValue` and `value` property
         */
        this.change = new EventEmitter();
        /**
         * button group type, either 'radio' or 'checkbox'
         * @default checkbox
         */
        this.type = 'checkbox';
        /**
         * Whether the button group is disabled
         * @default false
         */
        this.disabled = false;
        /**
         * @docs-private
         */
        this.disabledChange = new EventEmitter();
    }
    ButtonGroupComponent.prototype.ngOnInit = function () {
        var _this = this;
        var self = this;
        // listen to disabled property, and update children disabled state
        self.disabledChange.subscribe(function (disabled) {
            self._disableButtonList(disabled);
        });
        // update init value
        if (this.value && this.datasource) {
            this.datasource.forEach(function (item) {
                item.checked = item.checked || _this.value.includes(item.value);
                // update checked value
                if (item.checked) {
                    _this.value = Array.from(new Set(_this.value).add(item.value));
                }
            });
        }
    };
    ButtonGroupComponent.prototype.ngAfterContentInit = function () {
        this._disableButtonList(this.disabled);
    };
    ButtonGroupComponent.prototype._disableButtonList = function (groupDisabled) {
        var self = this;
        var buttonList = this._getButtonList();
        if (buttonList) {
            buttonList.forEach(function (button) {
                button.disabled = button.disabled || groupDisabled;
            });
        }
    };
    ButtonGroupComponent.prototype._getButtonList = function () {
        var hasDatasource = this.datasource && this.datasource.length;
        return hasDatasource ? this._viewButtonList : this._contentButtonList;
    };
    /**
     * set children toggle button checked state
     *
     * @param {any} value - current toggle button value
     * @docs-private
     */
    ButtonGroupComponent.prototype.select = function (value) {
        var buttonList = this._getButtonList();
        if (!buttonList) {
            console.error('无法进行选择操作，此时所有按钮组还未生成。');
            return;
        }
        if (this.type === 'radio') {
            buttonList.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 button = buttonList.find(function (v) { return (v.value + '') === (value + ''); });
            var valueSet = new Set(this.value);
            if (button) {
                button.checked = !button.checked;
                button.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.
     */
    ButtonGroupComponent.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.
     */
    ButtonGroupComponent.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.
     */
    ButtonGroupComponent.prototype.writeValue = function (value) {
        if (value && !Array.isArray(value)) {
            throw new Error('使用表单赋值时，button-group 的值必须传入数组形式，即使单选框也一样');
        }
        if (value) {
            this.value = value;
            // when init, set children toggle button state
            this._forceUpdateValue(value);
        }
    };
    /**
     * Toggles the disabled state of the component. Implemented as part of ControlValueAccessor.
     * @param isDisabled Whether the component should be disabled.
     */
    ButtonGroupComponent.prototype.setDisabledState = function (isDisabled) {
        this.disabled = isDisabled;
    };
    /**
     * update form model value and mark for check
     */
    ButtonGroupComponent.prototype._updateFormModel = function () {
        if (this._onModelChange) {
            this._onModelChange(this.value);
        }
        if (this._onTouch) {
            this._onTouch(this.value);
        }
    };
    /**
     * force update box group value
     *
     * @param {any[]} value
     * @returns
     */
    ButtonGroupComponent.prototype._forceUpdateValue = function (value) {
        var boxList = this._getButtonList();
        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 + ''); });
        }
        var currentValue = Array.isArray(value) && value.length ? value[value.length - 1] : '';
        // emit change value
        this.change.emit({
            currentValue: currentValue,
            value: this.value
        });
        this._cd.markForCheck();
    };
    tslib_1.__decorate([
        Output(),
        tslib_1.__metadata("design:type", EventEmitter)
    ], ButtonGroupComponent.prototype, "change", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", String)
    ], ButtonGroupComponent.prototype, "type", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Array)
    ], ButtonGroupComponent.prototype, "datasource", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Object)
    ], ButtonGroupComponent.prototype, "value", void 0);
    tslib_1.__decorate([
        OnChange(true),
        Input(),
        tslib_1.__metadata("design:type", Object)
    ], ButtonGroupComponent.prototype, "disabled", void 0);
    tslib_1.__decorate([
        ContentChildren(forwardRef(function () { return ButtonToggleComponent; })),
        tslib_1.__metadata("design:type", QueryList)
    ], ButtonGroupComponent.prototype, "_contentButtonList", void 0);
    tslib_1.__decorate([
        ViewChildren(forwardRef(function () { return ButtonToggleComponent; })),
        tslib_1.__metadata("design:type", QueryList)
    ], ButtonGroupComponent.prototype, "_viewButtonList", void 0);
    ButtonGroupComponent = tslib_1.__decorate([
        Component({
            selector: 'nb-button-group',
            template: "<ng-container *ngIf=\"datasource && datasource.length\"><nb-button-toggle *ngFor=\"let d of datasource\" [value]=\"d.value\" [checked]=\"d.checked\" [disabled]=\"d.disabled\">{{ d.text }}</nb-button-toggle></ng-container><ng-container *ngIf=\"!datasource\"><ng-content></ng-content></ng-container>",
            encapsulation: ViewEncapsulation.None,
            changeDetection: ChangeDetectionStrategy.OnPush,
            preserveWhitespaces: false,
            providers: [BUTTONGROUP_VALUE_ACCESSOR],
            host: {
                'class': 'nb-widget nb-button-group'
            },
            exportAs: 'nbButtonGroup'
        }),
        tslib_1.__metadata("design:paramtypes", [ChangeDetectorRef])
    ], ButtonGroupComponent);
    return ButtonGroupComponent;
}());
export { ButtonGroupComponent };
/**
 * A single toggle button, usually used in `nb-button-group`,
 * like checkbox, it has a associated value and can be checked and disabled
 */
var ButtonToggleComponent = /** @class */ (function () {
    /**
     * Creates an instance of ButtonToggleComponent.
     * @param {ButtonGroupComponent?} buttonGroup - the optional wrapped parent button group component
     */
    function ButtonToggleComponent(buttonGroup) {
        /** toggle event, emit a boolean value */
        this.toggle = new EventEmitter();
        /**
         * toggle button's value, can be any type
         * @default ''
         */
        this.value = '';
        /**
         * Whether toggle button is checked
         * @default false
         */
        this.checked = false;
        /**
         * Whether toggle button is disabled
         * @default false
         */
        this.disabled = false;
        this.buttonGroup = buttonGroup;
    }
    /**
     * Toggle event
     *
     * @docs-private
     */
    ButtonToggleComponent.prototype.onToggle = function () {
        if (this.disabled) {
            return;
        }
        // if not a single toggle button, tell the parent button group component
        // to toggle proper buttons according to type
        if (this.buttonGroup) {
            this.buttonGroup.select(this.value);
        }
        // if a single toggle button, just emit the toggle event
        else {
            this.checked = !this.checked;
            this.toggle.emit(this.checked);
        }
    };
    tslib_1.__decorate([
        Output(),
        tslib_1.__metadata("design:type", EventEmitter)
    ], ButtonToggleComponent.prototype, "toggle", void 0);
    tslib_1.__decorate([
        Input(),
        tslib_1.__metadata("design:type", Object)
    ], ButtonToggleComponent.prototype, "value", void 0);
    tslib_1.__decorate([
        OnChange(true),
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], ButtonToggleComponent.prototype, "checked", void 0);
    tslib_1.__decorate([
        OnChange(true),
        Input(),
        tslib_1.__metadata("design:type", Boolean)
    ], ButtonToggleComponent.prototype, "disabled", void 0);
    ButtonToggleComponent = tslib_1.__decorate([
        Component({
            selector: 'nb-button-toggle',
            template: "\n        <span class=\"nb-button-inner\"><ng-content></ng-content></span>\n    ",
            encapsulation: ViewEncapsulation.None,
            changeDetection: ChangeDetectionStrategy.OnPush,
            preserveWhitespaces: false,
            host: {
                'class': 'nb-widget nb-button-toggle',
                '[class.nb-button-toggle-checked]': 'checked',
                '[class.nb-button-toggle-disabled]': 'disabled',
                '(click)': 'onToggle()'
            },
            exportAs: 'nbButtonToggle'
        }),
        tslib_1.__param(0, Optional()),
        tslib_1.__metadata("design:paramtypes", [ButtonGroupComponent])
    ], ButtonToggleComponent);
    return ButtonToggleComponent;
}());
export { ButtonToggleComponent };
//# sourceMappingURL=button-group.js.map