import { Component, Input, ViewChild } from '@angular/core';
import { merge, Subject } from 'rxjs';
import { distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { FormControlBase } from "../form-control-base";
import * as i0 from "@angular/core";
import * as i1 from "../../core/validation-message.service";
import * as i2 from "../../shared/form-group.helper";
import * as i3 from "@angular/common";
import * as i4 from "@angular/forms";
import * as i5 from "../help-popover/help-popover.component";
import * as i6 from "@ngx-translate/core";
export class CheckboxComponent extends FormControlBase {
    constructor(validationMessageService, formGroupHelper) {
        super(validationMessageService, formGroupHelper);
        this.validationMessageService = validationMessageService;
        this.formGroupHelper = formGroupHelper;
        /**
         * The name of the checkbox input element
         */
        this.name = '';
        /**
         * Determines whether to ignore or include disabled dependent checkboxes in the check to determine the checkbox state.
         */
        this.ignoreDisabledDependents = true;
        /**
         * If the checkbox is a master checkbox (i.e. it has a dependentCheckboxesGroup),
         * indeterminate is true if there are some checked dependents and some unchecked dependents.
         */
        this.indeterminate = false;
        //Used to prevent valueChanges loops in the master checkbox and dependent checkboxes value changes.
        this.ignoreCall = false;
        /** Fired whenever the dependent checkboxes are changed to clear out subscriptions to the previous dependents */
        this.resetDependentSubscriptions = new Subject();
    }
    ngAfterViewInit() {
        if (this.autofocus) {
            this.inputElement.nativeElement.focus();
        }
    }
    ngOnChanges(changes) {
        if (changes.dependentCheckboxesGroup) {
            this.setupDependents();
        }
    }
    dispatchEvent(event) {
        if (event.type === 'click' && !this.formModel.disabled) {
            this.formModel.patchValue(!this.formModel.value);
        }
    }
    /**
     * Create watchers that allow the master and dependent checkbox states to stay in sync as the user interacts with them.
     * Dependents can update the master when their values change and the master updates dependents when the value changes.
     */
    setupDependents() {
        if (!this.dependentCheckboxesGroup) {
            return;
        }
        // Remove any subscriptions to previous dependents
        this.resetDependentSubscriptions.next();
        //Extract the values (i.e. the checkboxes) from the FormGroup controls key-value map and return them. 
        let dependentCheckboxes = Object.values(this.dependentCheckboxesGroup.controls);
        this.updateMasterState(dependentCheckboxes);
        //When the master value changes, we set all its dependents to that value.
        //We also set indeterminate to false since we know that all dependents will either be checked or unchecked.
        this.formModel.valueChanges.pipe(distinctUntilChanged(), takeUntil(merge(this.componentDestroyed, this.resetDependentSubscriptions))).subscribe((value) => {
            if (!this.ignoreCall) {
                this.ignoreCall = true; //Ignore any value changes calls on the dependents to prevent a loop.
                dependentCheckboxes.forEach(checkbox => {
                    if (!checkbox.disabled || !this.ignoreDisabledDependents) {
                        checkbox.setValue(value);
                    }
                });
                this.indeterminate = false;
                this.ignoreCall = false;
            }
        });
        //When a dependent value changes, we need to reevaluate the master state.
        //We are subscribing to the form models directly instead of the entire group because we found that adding checkboxes to 
        //  more than one form group causes only the last group to emit valueChanges events. 
        //That prevented combined row-master and table-master setups from working properly.
        dependentCheckboxes.forEach(checkbox => {
            checkbox.valueChanges.pipe(distinctUntilChanged(), takeUntil(merge(this.componentDestroyed, this.resetDependentSubscriptions))).subscribe((value) => {
                if (value !== true && value !== false) {
                    console.error(`The value ${value} is not true or false, which are the only supported values for FormControls in the dependentCheckboxesGroup`);
                    return;
                }
                if (!this.ignoreCall) {
                    this.ignoreCall = true; //Ignore any value changes calls on the master to prevent a loop.
                    this.updateMasterState(dependentCheckboxes);
                    this.ignoreCall = false;
                }
            });
        });
    }
    /**
     * If all dependents are true, the master should be true and determinate.
     * If all dependents are false, the master should be false and determinate.
     * If some dependents are true and some dependents are false, the master should be false and indeterminate.
     *
     * If ignoreDisabledDependents is true, does not include the disabled dependents when checking values
    */
    updateMasterState(dependentCheckboxes) {
        let dependentsToCheck = [];
        if (this.ignoreDisabledDependents) {
            dependentsToCheck = dependentCheckboxes.filter(checkbox => checkbox.enabled);
        }
        else {
            dependentsToCheck = dependentCheckboxes;
        }
        let isTrue = (checkbox) => { return checkbox.value === true; };
        if (dependentsToCheck.every(isTrue)) {
            this.formModel.setValue(true);
            this.indeterminate = false;
        }
        else if (dependentsToCheck.some(isTrue)) {
            this.formModel.setValue(false);
            this.indeterminate = true;
        }
        else {
            this.formModel.setValue(false);
            this.indeterminate = false;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CheckboxComponent, deps: [{ token: i1.ValidationMessageService }, { token: i2.FormGroupHelper }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CheckboxComponent, selector: "ec-checkbox", inputs: { name: "name", dependentCheckboxesGroup: "dependentCheckboxesGroup", ignoreDisabledDependents: "ignoreDisabledDependents" }, viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["checkboxInput"], descendants: true, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"control\">\r\n       <label class=\"checkbox\"\r\n              [ngClass]=\"{'is-disabled': formModel.disabled, 'no-label': !label, 'is-readonly': readonly}\">\r\n              <input id=\"{{id}}_input\"\r\n                     #checkboxInput\r\n                     class='input'\r\n                     [class.indeterminate]=\"indeterminate\"\r\n                     [attr.id]=\"inputId\"\r\n                     [attr.name]=\"name\"\r\n                     type=\"checkbox\"\r\n                     tabindex=\"{{tabindex}}\"\r\n                     [formControl]=\"formModel\"\r\n                     [attr.cdkFocusInitial]=\"autofocus || null\">\r\n              <i class=\"ec-icon icon-check\"></i>\r\n\r\n              <span id=\"{{id}}_label\"\r\n                    *ngIf=\"label\"\r\n                    class=\"label\">\r\n                     <span [innerHtml]=\"label | translate\"></span>\r\n                     <ec-help-popover id=\"{{id}}_helpPopover\"\r\n                                      *ngIf=\"helpPopover\"\r\n                                      class=\"d-inline-block my-n2 mx-n1\"\r\n                                      text=\"{{helpPopover | translate}}\"\r\n                                      contentPosition=\"{{helpPopoverPosition}}\">\r\n                     </ec-help-popover>\r\n              </span>\r\n       </label>\r\n</div>", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:none}:host(.w-auto){width:auto}.checkbox{cursor:pointer;display:inline-flex;margin-bottom:0;position:relative}.checkbox.is-disabled{cursor:default}.input{margin-top:.5rem;opacity:0;position:absolute;z-index:-1}.input:not(:checked)+.ec-icon{color:var(--ec-form-control-border-color)}.input:not(:checked)+.ec-icon:before{display:none}.input.indeterminate+.ec-icon,.input:indeterminate+.ec-icon{color:var(--ec-color-interactive)}.input.indeterminate+.ec-icon:before,.input:indeterminate+.ec-icon:before{content:\"\";background-color:currentColor;display:block;width:10px;height:3px}.input:focus+.ec-icon{color:var(--ec-color-interactive);box-shadow:var(--ec-form-control-box-shadow-focus);border-color:var(--ec-form-control-border-color-focus)}.input:disabled+.ec-icon{color:var(--ec-form-control-color-disabled);background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}.input:disabled~.label{color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}.ec-icon{background-color:var(--ec-form-control-background-color);background-clip:padding-box;border:1px solid currentColor;color:var(--ec-color-interactive);margin-top:.5rem;flex:none;pointer-events:none;display:inline-flex;align-items:center;justify-content:center;height:1em;width:1em;border-radius:.125rem}.ec-icon:before{font-size:.6875em}.label{line-height:1.25rem;padding:.375rem 0;margin-left:.5rem;min-height:2rem;height:auto}.checkbox.is-readonly{pointer-events:none}.checkbox.is-readonly .input{opacity:0}.checkbox.is-readonly .ec-icon{background-color:var(--ec-form-control-background-color-readonly);border-color:var(--ec-form-control-border-color-readonly)}.checkbox.is-readonly .label,.checkbox.is-readonly .ec-icon{opacity:1;color:var(--ec-form-control-color)}.no-label .input,.no-label .icon-check{margin-top:0}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i5.HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CheckboxComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ec-checkbox', template: "<div class=\"control\">\r\n       <label class=\"checkbox\"\r\n              [ngClass]=\"{'is-disabled': formModel.disabled, 'no-label': !label, 'is-readonly': readonly}\">\r\n              <input id=\"{{id}}_input\"\r\n                     #checkboxInput\r\n                     class='input'\r\n                     [class.indeterminate]=\"indeterminate\"\r\n                     [attr.id]=\"inputId\"\r\n                     [attr.name]=\"name\"\r\n                     type=\"checkbox\"\r\n                     tabindex=\"{{tabindex}}\"\r\n                     [formControl]=\"formModel\"\r\n                     [attr.cdkFocusInitial]=\"autofocus || null\">\r\n              <i class=\"ec-icon icon-check\"></i>\r\n\r\n              <span id=\"{{id}}_label\"\r\n                    *ngIf=\"label\"\r\n                    class=\"label\">\r\n                     <span [innerHtml]=\"label | translate\"></span>\r\n                     <ec-help-popover id=\"{{id}}_helpPopover\"\r\n                                      *ngIf=\"helpPopover\"\r\n                                      class=\"d-inline-block my-n2 mx-n1\"\r\n                                      text=\"{{helpPopover | translate}}\"\r\n                                      contentPosition=\"{{helpPopoverPosition}}\">\r\n                     </ec-help-popover>\r\n              </span>\r\n       </label>\r\n</div>", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:none}:host(.w-auto){width:auto}.checkbox{cursor:pointer;display:inline-flex;margin-bottom:0;position:relative}.checkbox.is-disabled{cursor:default}.input{margin-top:.5rem;opacity:0;position:absolute;z-index:-1}.input:not(:checked)+.ec-icon{color:var(--ec-form-control-border-color)}.input:not(:checked)+.ec-icon:before{display:none}.input.indeterminate+.ec-icon,.input:indeterminate+.ec-icon{color:var(--ec-color-interactive)}.input.indeterminate+.ec-icon:before,.input:indeterminate+.ec-icon:before{content:\"\";background-color:currentColor;display:block;width:10px;height:3px}.input:focus+.ec-icon{color:var(--ec-color-interactive);box-shadow:var(--ec-form-control-box-shadow-focus);border-color:var(--ec-form-control-border-color-focus)}.input:disabled+.ec-icon{color:var(--ec-form-control-color-disabled);background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}.input:disabled~.label{color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}.ec-icon{background-color:var(--ec-form-control-background-color);background-clip:padding-box;border:1px solid currentColor;color:var(--ec-color-interactive);margin-top:.5rem;flex:none;pointer-events:none;display:inline-flex;align-items:center;justify-content:center;height:1em;width:1em;border-radius:.125rem}.ec-icon:before{font-size:.6875em}.label{line-height:1.25rem;padding:.375rem 0;margin-left:.5rem;min-height:2rem;height:auto}.checkbox.is-readonly{pointer-events:none}.checkbox.is-readonly .input{opacity:0}.checkbox.is-readonly .ec-icon{background-color:var(--ec-form-control-background-color-readonly);border-color:var(--ec-form-control-border-color-readonly)}.checkbox.is-readonly .label,.checkbox.is-readonly .ec-icon{opacity:1;color:var(--ec-form-control-color)}.no-label .input,.no-label .icon-check{margin-top:0}\n"] }]
        }], ctorParameters: () => [{ type: i1.ValidationMessageService }, { type: i2.FormGroupHelper }], propDecorators: { name: [{
                type: Input
            }], dependentCheckboxesGroup: [{
                type: Input
            }], ignoreDisabledDependents: [{
                type: Input
            }], inputElement: [{
                type: ViewChild,
                args: ['checkboxInput', { static: true }]
            }] } });
//# sourceMappingURL=data:application/json;base64, 