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) {
        this.onModelValueChangeFunction?.(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() {
        this.interceptor?.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() {
        this.interceptor?.onModelValueChanged$
            .pipe(map((modelValue) => this.toViewValue(modelValue)), takeUntil(this.onDestroy$))
            .subscribe((viewValue) => this.interceptor?.pushViewValue(viewValue));
    }
    listenViewConvertToModelValue() {
        this.interceptor?.onViewValueChanged$
            .pipe(map((viewValue) => this.toModelValue(viewValue)), takeUntil(this.onDestroy$))
            .subscribe((modelValue) => this.interceptor?.pushModelValue(modelValue));
    }
}
/** @nocollapse */ ControlValueInterceptor.ɵfac = function ControlValueInterceptor_Factory(t) { return new (t || ControlValueInterceptor)(i0.ɵɵinject(NG_VALUE_ACCESSOR, 2)); };
/** @nocollapse */ ControlValueInterceptor.ɵprov = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjectable({ token: ControlValueInterceptor, factory: ControlValueInterceptor.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ControlValueInterceptor, [{
        type: Injectable
    }], function () { return [{ type: undefined, decorators: [{
                type: Inject,
                args: [NG_VALUE_ACCESSOR]
            }, {
                type: Self
            }] }]; }, null); })();

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

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