import * as i0 from '@angular/core';
import { Injectable, Inject, Self } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { exclude } from '@angular-ru/cdk/array';
import { isFunctionLike } from '@angular-ru/cdk/function';
import { Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';

class ControlValueAccessorPatcher {
    constructor(accessor) {
        this.accessor = accessor;
        this.onViewValueChangedSubject$ = new Subject();
        this.onModelValueChangedSubject$ = new Subject();
        this.onViewValueChanged$ = this.onViewValueChangedSubject$.asObservable();
        this.onModelValueChanged$ = this.onModelValueChangedSubject$.asObservable();
        this.saveOriginalAccessorFunctions();
        this.patchAccessorFunctions();
    }
    pushModelValue(modelValue) {
        var _a;
        (_a = this.onModelValueChangeFunction) === null || _a === void 0 ? void 0 : _a.call(this, modelValue);
    }
    pushViewValue(viewValue) {
        this.writeViewValueFunction(viewValue);
    }
    detach() {
        this.accessor.registerOnChange = this.registerOnViewValueChangeFunction;
        this.accessor.registerOnChange(this.onModelValueChangeFunction);
        this.accessor.writeValue = this.writeViewValueFunction;
    }
    patchAccessorFunctions() {
        this.accessor.registerOnChange = (onModelValueChangeFunction) => {
            this.onModelValueChangeFunction = onModelValueChangeFunction;
            const proxyUpdateViewValue = (viewValue) => {
                this.onViewValueChangedSubject$.next(viewValue);
            };
            this.registerOnViewValueChangeFunction(proxyUpdateViewValue);
        };
        this.accessor.writeValue = (modelValue) => {
            this.onModelValueChangedSubject$.next(modelValue);
        };
    }
    saveOriginalAccessorFunctions() {
        this.writeViewValueFunction = this.accessor.writeValue.bind(this.accessor);
        this.registerOnViewValueChangeFunction = this.accessor.registerOnChange.bind(this.accessor);
    }
}

class ControlValueInterceptor {
    constructor(accessors) {
        this.onDestroy$ = new Subject();
        this.controlValueOperators = [];
        const [accessor] = accessors;
        if (accessor) {
            this.interceptor = new ControlValueAccessorPatcher(accessor);
        }
        this.makeSequencesAndPassValues();
    }
    ngOnDestroy() {
        var _a;
        (_a = this.interceptor) === null || _a === void 0 ? void 0 : _a.detach();
        this.onDestroy$.next();
        this.onDestroy$.complete();
    }
    attach(descriptor) {
        this.controlValueOperators = this.controlValueOperators.concat(descriptor);
    }
    detach(descriptor) {
        this.controlValueOperators = this.controlValueOperators.filter(exclude(descriptor));
    }
    toModelValue(viewValue) {
        let value = viewValue;
        for (const operator of this.controlValueOperators) {
            value = isFunctionLike(operator.toModelValue) ? operator.toModelValue(value) : value;
        }
        return value;
    }
    toViewValue(modelValue) {
        let value = modelValue;
        for (const operator of this.controlValueOperators) {
            value = isFunctionLike(operator.toViewValue) ? operator.toViewValue(value) : value;
        }
        return value;
    }
    makeSequencesAndPassValues() {
        this.listenViewConvertToModelValue();
        this.listenModelConvertToViewValue();
    }
    listenModelConvertToViewValue() {
        var _a;
        (_a = this.interceptor) === null || _a === void 0 ? void 0 : _a.onModelValueChanged$.pipe(map((modelValue) => this.toViewValue(modelValue)), takeUntil(this.onDestroy$)).subscribe((viewValue) => { var _a; return (_a = this.interceptor) === null || _a === void 0 ? void 0 : _a.pushViewValue(viewValue); });
    }
    listenViewConvertToModelValue() {
        var _a;
        (_a = this.interceptor) === null || _a === void 0 ? void 0 : _a.onViewValueChanged$.pipe(map((viewValue) => this.toModelValue(viewValue)), takeUntil(this.onDestroy$)).subscribe((modelValue) => { var _a; return (_a = this.interceptor) === null || _a === void 0 ? void 0 : _a.pushModelValue(modelValue); });
    }
}
/** @nocollapse */ ControlValueInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: ControlValueInterceptor, deps: [{ token: NG_VALUE_ACCESSOR, self: true }], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ ControlValueInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: ControlValueInterceptor });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: ControlValueInterceptor, decorators: [{
            type: Injectable
        }], ctorParameters: function () {
        return [{ type: undefined, decorators: [{
                        type: Inject,
                        args: [NG_VALUE_ACCESSOR]
                    }, {
                        type: Self
                    }] }];
    } });

/**
 * Generated bundle index. Do not edit.
 */

export { ControlValueInterceptor };
//# sourceMappingURL=angular-ru-cdk-forms.mjs.map
