import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { EventEmitter, ChangeDetectorRef, Attribute, Self, Optional, Input, Output, Component, ViewEncapsulation, ChangeDetectionStrategy, isDevMode, NgZone, ContentChildren, NgModule } from '@angular/core';
import { NgControl } from '@angular/forms';
import { Subject, defer, merge } from 'rxjs';
import { take, switchMap, startWith, takeUntil } from 'rxjs/operators';
import { NtFormFieldControl } from '@ng-tangram/components/forms';
import { CommonModule } from '@angular/common';

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
let uniqueId = 0;
class NtCheckboxChange {
    constructor(source, checked) {
        this.source = source;
        this.checked = checked;
    }
}
let NtCheckboxComponent = class NtCheckboxComponent {
    constructor(_changeDetectorRef, tabIndex, ngControl) {
        this._changeDetectorRef = _changeDetectorRef;
        this.ngControl = ngControl;
        this.id = `nt-checkbox-${uniqueId++}`;
        this._disabled = false;
        this._readonly = false;
        this._checked = false;
        this._indeterminate = false;
        this.change = new EventEmitter();
        this.indeterminateChange = new EventEmitter();
        this._onChange = () => { };
        this._onTouched = () => { };
        if (this.ngControl) {
            this.ngControl.valueAccessor = this;
        }
        this.tabIndex = parseInt(tabIndex) || 0;
    }
    get value() { return this._value; }
    set value(value) { this._value = value; }
    get disabled() { return this._disabled; }
    set disabled(value) {
        if (value !== this.disabled) {
            this._disabled = coerceBooleanProperty(value);
            this._changeDetectorRef.markForCheck();
        }
    }
    get readonly() { return this._readonly; }
    set readonly(value) { this._readonly = coerceBooleanProperty(value); }
    get checked() { return this._checked; }
    set checked(value) {
        if (value !== this.checked) {
            this._checked = coerceBooleanProperty(value);
            this._changeDetectorRef.markForCheck();
        }
    }
    get indeterminate() { return this._indeterminate; }
    set indeterminate(value) {
        const changed = value !== this._indeterminate;
        this._indeterminate = value;
        if (changed) {
            this.indeterminateChange.emit(this._indeterminate);
        }
    }
    writeValue(value) {
        this._checked = !!value;
    }
    registerOnChange(fn) {
        this._onChange = fn;
    }
    registerOnTouched(fn) {
        this._onTouched = fn;
    }
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
    }
    _onInputClick(event) {
        event.stopPropagation();
        if (!this.disabled) {
            this._checked = !this._checked;
            this._onTouched();
            this._emitChangeEvent();
        }
    }
    _onInteractionEvent(event) {
        event.stopPropagation();
    }
    _emitChangeEvent() {
        const event = new NtCheckboxChange(this, this.checked);
        this._onChange(this.checked);
        this.change.emit(event);
    }
};
NtCheckboxComponent.ctorParameters = () => [
    { type: ChangeDetectorRef },
    { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] },
    { type: NgControl, decorators: [{ type: Self }, { type: Optional }] }
];
__decorate([
    Input()
], NtCheckboxComponent.prototype, "value", null);
__decorate([
    Input()
], NtCheckboxComponent.prototype, "disabled", null);
__decorate([
    Input()
], NtCheckboxComponent.prototype, "readonly", null);
__decorate([
    Input()
], NtCheckboxComponent.prototype, "checked", null);
__decorate([
    Input()
], NtCheckboxComponent.prototype, "indeterminate", null);
__decorate([
    Output()
], NtCheckboxComponent.prototype, "change", void 0);
__decorate([
    Output()
], NtCheckboxComponent.prototype, "indeterminateChange", void 0);
NtCheckboxComponent = __decorate([
    Component({
        selector: 'nt-checkbox',
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush,
        template: "<label class=\"nt-checkbox-layout\">\n  <div class=\"nt-checkbox-input-container\">\n    <input class=\"cdk-visually-hidden\"\n      type=\"checkbox\"\n      [tabIndex]=\"tabIndex\"\n      [checked]=\"checked\"\n      [disabled]=\"disabled\"\n      [readonly]=\"readonly\"\n      (change)=\"_onInteractionEvent($event)\"\n      (click)=\"_onInputClick($event)\">\n    <div class=\"nt-checkbox-input nt-form-control\"></div>\n  </div>\n  <span class=\"nt-checkbox-label\">\n    <ng-content></ng-content>\n  </span>\n</label>\n",
        host: {
            'class': 'nt-checkbox',
            '[class.nt-checkbox-checked]': 'checked',
            '[class.nt-checkbox-disabled]': 'disabled',
            '[class.nt-checkbox-indeterminate]': 'indeterminate',
        }
    }),
    __param(1, Attribute('tabindex')),
    __param(2, Self()), __param(2, Optional())
], NtCheckboxComponent);

var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param$1 = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var NtCheckboxGroupComponent_1;
function getNtCheckboxGroupNonFunctionValueError() {
    return Error('`compareWith` must be a function.');
}
let uniqueId$1 = 0;
let NtCheckboxGroupComponent = NtCheckboxGroupComponent_1 = class NtCheckboxGroupComponent extends NtFormFieldControl {
    constructor(_ngZone, _changeDetectorRef, ngControl) {
        super();
        this._ngZone = _ngZone;
        this._changeDetectorRef = _changeDetectorRef;
        this.ngControl = ngControl;
        this.id = `nt-checkbox-group-${uniqueId$1++}`;
        this._destroy = new Subject();
        this._disabled = false;
        this._readonly = false;
        this._required = false;
        this._compareWith = (o1, o2) => o1 === o2;
        this.checkedChanges = defer(() => {
            if (this.checkboxes) {
                return merge(...this.checkboxes.map(item => item.change));
            }
            return this._ngZone.onStable
                .asObservable()
                .pipe(take(1), switchMap(() => this.checkedChanges));
        });
        this._onChange = () => { };
        this._onTouched = () => { };
        if (this.ngControl) {
            this.ngControl.valueAccessor = this;
        }
    }
    get value() { return this._value; }
    set disabled(value) { this._disabled = coerceBooleanProperty(value); }
    get disabled() { return this._disabled; }
    get required() { return this._required; }
    set required(value) { this._required = coerceBooleanProperty(value); }
    set readonly(value) { this._readonly = coerceBooleanProperty(value); }
    get readonly() { return this._readonly; }
    set compareWith(fn) {
        if (typeof fn !== 'function') {
            throw getNtCheckboxGroupNonFunctionValueError();
        }
        else {
            this._compareWith = fn;
        }
    }
    ngAfterViewInit() {
        this.checkboxes.changes.pipe(startWith(null), takeUntil(this._destroy)).subscribe(() => {
            this._resetCheckboxs();
            this._initializeChecked();
        });
    }
    ngOnDestroy() {
        this._destroy.next();
        this._destroy.complete();
    }
    writeValue(value) {
        if (this.checkboxes) {
            this._setCheckedByValue(value);
        }
    }
    registerOnChange(fn) {
        this._onChange = fn;
    }
    registerOnTouched(fn) {
        this._onTouched = fn;
    }
    focus() {
        if (!this.disabled) {
            this._onTouched();
        }
    }
    _initializeChecked() {
        Promise.resolve().then(() => {
            this._setCheckedByValue(this.ngControl ? this.ngControl.value : this.value);
        });
    }
    _resetCheckboxs() {
        const changedOrDestroyed = merge(this.checkboxes.changes, this._destroy);
        this.checkedChanges.pipe(takeUntil(changedOrDestroyed)).subscribe(() => {
            this._setValues();
        });
        merge(...this.checkboxes.map(item => item.change))
            .pipe(takeUntil(changedOrDestroyed))
            .subscribe(() => {
            this._changeDetectorRef.markForCheck();
        });
    }
    _setCheckedByValue(value) {
        if (value) {
            this._value = value;
            this.checkboxes.forEach(item => item.checked = false);
            value.forEach(val => this._checkedValue(val));
            this._changeDetectorRef.markForCheck();
        }
    }
    _checkedValue(value) {
        const correspondingItem = this.checkboxes.find((item) => {
            try {
                return item.value != null && this._compareWith(item.value, value);
            }
            catch (error) {
                if (isDevMode()) {
                    console.warn(error);
                }
                return false;
            }
        });
        if (correspondingItem) {
            correspondingItem.checked = true;
        }
        return correspondingItem;
    }
    _setValues() {
        this._value = [];
        this.checkboxes.forEach(item => {
            if (item.checked && !!item.value) {
                this._value.push(item.value);
            }
        });
        this._onChange(this._value);
        this._onTouched();
        this._changeDetectorRef.markForCheck();
    }
};
NtCheckboxGroupComponent.ctorParameters = () => [
    { type: NgZone },
    { type: ChangeDetectorRef },
    { type: NgControl, decorators: [{ type: Self }, { type: Optional }] }
];
__decorate$1([
    Input()
], NtCheckboxGroupComponent.prototype, "disabled", null);
__decorate$1([
    Input()
], NtCheckboxGroupComponent.prototype, "required", null);
__decorate$1([
    Input()
], NtCheckboxGroupComponent.prototype, "readonly", null);
__decorate$1([
    ContentChildren(NtCheckboxComponent)
], NtCheckboxGroupComponent.prototype, "checkboxes", void 0);
__decorate$1([
    Input()
], NtCheckboxGroupComponent.prototype, "compareWith", null);
NtCheckboxGroupComponent = NtCheckboxGroupComponent_1 = __decorate$1([
    Component({
        selector: 'nt-checkbox-group',
        template: '<ng-content></ng-content>',
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush,
        providers: [
            { provide: NtFormFieldControl, useExisting: NtCheckboxGroupComponent_1 }
        ],
        host: {
            'class': 'nt-checkbox-group'
        }
    }),
    __param$1(2, Self()), __param$1(2, Optional())
], NtCheckboxGroupComponent);

var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
let NtCheckboxModule = class NtCheckboxModule {
};
NtCheckboxModule = __decorate$2([
    NgModule({
        imports: [CommonModule],
        exports: [NtCheckboxComponent, NtCheckboxGroupComponent],
        declarations: [NtCheckboxComponent, NtCheckboxGroupComponent],
    })
], NtCheckboxModule);

export { NtCheckboxChange, NtCheckboxComponent, NtCheckboxGroupComponent, NtCheckboxModule, getNtCheckboxGroupNonFunctionValueError };
//# sourceMappingURL=checkbox.js.map
