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 __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Directive, ElementRef, Input } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';
import { CaseField } from '../../domain/definition/case-field.model';
import { ShowCondition } from './domain/conditional-show.model';
import { FieldsUtils } from '../../services/fields/fields.utils';
import { ConditionalShowRegistrarService } from './services/conditional-show-registrar.service';
import { GreyBarService } from './services/grey-bar.service';
import { ElementShowHideService } from './services';
var ConditionalShowDirective = /** @class */ (function () {
    function ConditionalShowDirective(el, fieldsUtils, registry, greyBarService, elementShowHideService) {
        this.el = el;
        this.fieldsUtils = fieldsUtils;
        this.registry = registry;
        this.greyBarService = greyBarService;
        this.elementShowHideService = elementShowHideService;
        this.contextFields = [];
        this.greyBarEnabled = false;
    }
    ConditionalShowDirective.prototype.ngAfterViewInit = function () {
        if (this.caseField.show_condition) {
            this.condition = new ShowCondition(this.caseField.show_condition);
            // console.log('FIELD: ' + this.caseField.id + ' init. Show condition: ' + this.caseField.show_condition);
            this.formGroup = this.formGroup || new FormGroup({});
            this.complexFormGroup = this.complexFormGroup || new FormGroup({});
            this.formField = this.complexFormGroup.get(this.caseField.id) || this.formGroup.get(this.caseField.id);
            // console.log('FIELD: ' + this.caseField.id + '. Is form field:' + this.formField + '. Event fields:', this.eventFields);
            this.updateVisibility(this.getCurrentPagesReadOnlyAndFormFieldValues());
            if (this.greyBarEnabled && this.greyBarService.wasToggledToShow(this.caseField.id)) {
                this.greyBarService.showGreyBar(this.caseField, this.el);
            }
            this.subscribeToFormChanges();
            this.registry.register(this);
        }
    };
    ConditionalShowDirective.prototype.refreshVisibility = function () {
        // console.log('Refresh FIELD: ', this.caseField.id, '. field:', this.formField, '. eventFields:', this.eventFields);
        this.updateVisibility(this.getCurrentPagesReadOnlyAndFormFieldValues(), true);
        this.subscribeToFormChanges();
    };
    ConditionalShowDirective.prototype.ngOnDestroy = function () {
        this.unsubscribeFromFormChanges();
    };
    ConditionalShowDirective.prototype.subscribeToFormChanges = function () {
        var _this = this;
        this.unsubscribeFromFormChanges();
        // console.log('FIELD ' + this.caseField.id + ' subscribing to form changes');
        this.formChangesSubscription = this.formGroup.valueChanges.subscribe(function (_) {
            // console.log('FIELD ' + this.caseField.id + ' reacting to form change');
            var shown = _this.updateVisibility(_this.getCurrentPagesReadOnlyAndFormFieldValues());
            if (_this.greyBarEnabled && shown !== undefined) {
                _this.updateGreyBar(shown);
            }
        });
    };
    /**
     * returns whether the field visibility has changed, or undefined if not
    */
    ConditionalShowDirective.prototype.updateVisibility = function (fields, forced) {
        if (forced === void 0) { forced = false; }
        // console.log('FIELD ' + this.caseField.id + ' updatingVisibility based on fields: ', fields, ' forced:', forced);
        if (this.shouldToggleToHide(fields, forced)) {
            this.onHide();
            return false;
        }
        else if (this.shouldToggleToShow(fields)) {
            this.onShow();
            return true;
        }
    };
    ConditionalShowDirective.prototype.onHide = function () {
        // console.log('on hide is form field', this.formField);
        if (this.formField) {
            this.unsubscribeFromFormChanges();
            // console.log('FIELD ' + this.caseField.id + ' disabling form field');
            this.formField.disable();
            this.subscribeToFormChanges();
        }
        this.hideField();
        this.greyBarService.removeGreyBar(this.el);
    };
    ConditionalShowDirective.prototype.onShow = function () {
        if (this.formField) {
            this.unsubscribeFromFormChanges();
            // console.log('FIELD ' + this.caseField.id + ' enabling form field', this.formField);
            this.formField.enable();
            this.subscribeToFormChanges();
        }
        this.showField();
        if (this.formField) {
            this.checkHideShowCondition(this.caseField.id, this.formField);
        }
    };
    ConditionalShowDirective.prototype.hideField = function () {
        this.elementShowHideService.hide(this.el);
    };
    ConditionalShowDirective.prototype.showField = function () {
        this.elementShowHideService.show(this.el);
    };
    ConditionalShowDirective.prototype.shouldToggleToHide = function (fields, forced) {
        return (!this.isHidden() || (this.formField && this.formField.enabled) || forced) && !this.condition.match(fields, this.buildPath());
    };
    ConditionalShowDirective.prototype.shouldToggleToShow = function (fields) {
        return (this.isHidden() || (this.formField && this.formField.disabled)) && (this.condition.match(fields, this.buildPath()));
    };
    ConditionalShowDirective.prototype.buildPath = function () {
        if (this.idPrefix) {
            return this.idPrefix + this.caseField.id;
        }
        return this.caseField.id;
    };
    ConditionalShowDirective.prototype.getCurrentPagesReadOnlyAndFormFieldValues = function () {
        var formFields = this.getFormFieldsValuesIncludingDisabled();
        // console.log('FIELD ' + this.caseField.id + ' current form values including disabled: ', formFields);
        return this.fieldsUtils.mergeCaseFieldsAndFormFields(this.contextFields, formFields);
    };
    ConditionalShowDirective.prototype.getFormFieldsValuesIncludingDisabled = function () {
        return this.formGroup.getRawValue();
    };
    ConditionalShowDirective.prototype.isHidden = function () {
        return this.elementShowHideService.isHidden(this.el);
    };
    ConditionalShowDirective.prototype.unsubscribeFromFormChanges = function () {
        if (this.formChangesSubscription) {
            this.formChangesSubscription.unsubscribe();
        }
    };
    // TODO This must be extracted to a generic service for traversing see RDM-2233
    ConditionalShowDirective.prototype.checkHideShowCondition = function (key, aControl) {
        var _this = this;
        if (aControl instanceof FormArray) { // We're in a collection
            // console.log('traversing array', aControl);
            aControl.controls.forEach(function (formControl, i) {
                // console.log('in array', formControl);
                _this.checkHideShowCondition('' + i, formControl);
            });
        }
        else if (aControl instanceof FormGroup) {
            // console.log('met a FormGroup ', aControl, ' fromGroup.controls', aControl.controls);
            if (aControl.get('value')) { // Complex Field
                var complexControl_1 = aControl.get('value');
                Object.keys(complexControl_1.controls).forEach(function (controlKey) {
                    // console.log('traversing formGroup item', key, complexControl.get(key));
                    _this.checkHideShowCondition(controlKey, complexControl_1.get(controlKey));
                });
            }
            else if (aControl.controls) { // Special Field like AddressUK, AddressGlobal
                Object.keys(aControl.controls).forEach(function (controlKey) {
                    // console.log('traversing formGroup item', key, aControl.get(key));
                    _this.checkHideShowCondition(controlKey, aControl.get(controlKey));
                });
            }
        }
        else if (aControl instanceof FormControl) { // FormControl
            if (aControl.invalid) {
                // console.log('met an invalid FormControl ', key, ' control:', aControl, ' is valid:', aControl.valid);
                this.registry.refresh();
            }
        }
    };
    ConditionalShowDirective.prototype.updateGreyBar = function (shown) {
        if (shown) {
            this.greyBarService.addToggledToShow(this.caseField.id);
            this.greyBarService.showGreyBar(this.caseField, this.el);
        }
        else {
            this.greyBarService.removeToggledToShow(this.caseField.id);
            this.greyBarService.removeGreyBar(this.el);
        }
    };
    __decorate([
        Input(),
        __metadata("design:type", CaseField)
    ], ConditionalShowDirective.prototype, "caseField", void 0);
    __decorate([
        Input(),
        __metadata("design:type", String)
    ], ConditionalShowDirective.prototype, "idPrefix", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Array)
    ], ConditionalShowDirective.prototype, "contextFields", void 0);
    __decorate([
        Input(),
        __metadata("design:type", FormGroup)
    ], ConditionalShowDirective.prototype, "formGroup", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object)
    ], ConditionalShowDirective.prototype, "greyBarEnabled", void 0);
    __decorate([
        Input(),
        __metadata("design:type", FormGroup)
    ], ConditionalShowDirective.prototype, "complexFormGroup", void 0);
    ConditionalShowDirective = __decorate([
        Directive({ selector: '[ccdConditionalShow]' })
        /** Hides and shows the host element based on the show condition if the condition is not empty. Works on read only fields and form fields.
         *  The show condition is evaluated on all the fields of the page. i.e. read only and form fields. When a form field is hidden, if its
         *  initial value was changed then the field is cleared. Otherwise the original value is kept and will display next time the field is
         *  shown. Evaluation of the show condition includes disabled fields, which can be on their initial value or empty. Executes on the
         *  host field initialization and when any field of the form changes.
         *  Collaborates with the GreyBarService to show a vertical grey bar when a field initially hidden on the page is shown. When returning
         *  to the page after the page has been left, the grey bar has to be redisplayed. If instead on initial page load the field renders as
         *  initially shown, the grey bar is not displayed.
         */
        ,
        __metadata("design:paramtypes", [ElementRef,
            FieldsUtils,
            ConditionalShowRegistrarService,
            GreyBarService,
            ElementShowHideService])
    ], ConditionalShowDirective);
    return ConditionalShowDirective;
}());
export { ConditionalShowDirective };
//# sourceMappingURL=conditional-show.directive.js.map