import * as i0 from '@angular/core';
import { InjectionToken, Injector, InjectFlags, INJECTOR, Injectable, Optional, Inject } from '@angular/core';
import { DefinitionMetadata, BaseDefinition, DefinitionLoader } from '@rxap/definition';
import { Subject } from 'rxjs';
import { RxapError } from '@rxap/utilities';
import { CounterSubject } from '@rxap/rxjs';

const REMOTE_METHOD_META_DATA = new InjectionToken('rxap/remote-method/REMOTE_METHOD_META_DATA');
const RXAP_PROXY_REMOTE_METHOD_TARGET = new InjectionToken('rxap/remote-method/proxy/target');

class RxapRemoteMethodError extends RxapError {
    constructor(message, code, className) {
        super('@rxap/remote-method', message, code, className);
    }
}

function RxapRemoteMethod(metadataOrId, className = 'BaseRemoteMethod', packageName = '@rxap/remote-method') {
    return function (target) {
        DefinitionMetadata(metadataOrId, className, packageName)(target);
    };
}
class BaseRemoteMethod extends BaseDefinition {
    constructor(injector = null, metaData = null) {
        super(metaData);
        this.executed$ = new Subject();
        this.executionsInProgress$ = new CounterSubject();
        this._pauseRefresh = false;
        if (injector === undefined) {
            throw new RxapRemoteMethodError('Injector is undefined. Ensure that the Injector is added to the deps property!', '', this.constructor.name);
        }
        this.injector = injector ?? Injector.NULL;
        if (typeof this.injector.get !== 'function') {
            throw new RxapRemoteMethodError('The property injector is not Injector like. Check the deps property!', '', this.constructor.name);
        }
    }
    async call(parameters) {
        this.init();
        this.executionsInProgress$.increase();
        const result = await this._call(parameters);
        this.executionsInProgress$.decrease();
        this.executed$.next(result);
        this.executed(result);
        return result;
    }
    executed(result) {
        if (!this._pauseRefresh) {
            this.refresh();
        }
    }
    pauseRefresh() {
        this._pauseRefresh = true;
    }
    resumeRefresh() {
        this._pauseRefresh = false;
    }
    refresh() {
        if (this.metadata.refresh) {
            for (const refresh of this.metadata.refresh) {
                const canRefresh = this.injector.get(refresh, null, InjectFlags.Optional);
                if (canRefresh) {
                    canRefresh.refresh();
                }
            }
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: BaseRemoteMethod, deps: [{ token: INJECTOR, optional: true }, { token: REMOTE_METHOD_META_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: BaseRemoteMethod }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: BaseRemoteMethod, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i0.Injector, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [INJECTOR]
                }] }, { type: undefined, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [REMOTE_METHOD_META_DATA]
                }] }] });

class ProxyRemoteMethod extends BaseRemoteMethod {
    constructor(remoteMethod, injector = null, metadata = remoteMethod.metadata) {
        super(injector, metadata);
        this.remoteMethod = remoteMethod;
    }
    async _call(parameters) {
        return this.remoteMethod.call(await this.transformParameters(parameters));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ProxyRemoteMethod, deps: [{ token: RXAP_PROXY_REMOTE_METHOD_TARGET }, { token: INJECTOR }, { token: REMOTE_METHOD_META_DATA }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ProxyRemoteMethod }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ProxyRemoteMethod, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: BaseRemoteMethod, decorators: [{
                    type: Inject,
                    args: [RXAP_PROXY_REMOTE_METHOD_TARGET]
                }] }, { type: i0.Injector, decorators: [{
                    type: Inject,
                    args: [INJECTOR]
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [REMOTE_METHOD_META_DATA]
                }] }] });

class RemoteMethodLoader extends DefinitionLoader {
    async call$(remoteMethodIdOrInstanceOrToken, parameters, metadata, injector, notFoundValue, flags) {
        return this
            .load(remoteMethodIdOrInstanceOrToken, metadata, injector, notFoundValue, flags)
            .call(parameters);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: RemoteMethodLoader, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: RemoteMethodLoader, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: RemoteMethodLoader, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

// region 
// endregion

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

export { BaseRemoteMethod, ProxyRemoteMethod, REMOTE_METHOD_META_DATA, RXAP_PROXY_REMOTE_METHOD_TARGET, RemoteMethodLoader, RxapRemoteMethod, RxapRemoteMethodError };
//# sourceMappingURL=rxap-remote-method.mjs.map
