import { NgIf, JsonPipe } from '@angular/common';
import * as i0 from '@angular/core';
import { signal, Component, ChangeDetectionStrategy, Inject, Input, isDevMode, Injectable, Optional, InjectionToken } from '@angular/core';
import * as i1 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i2 from '@angular/material/progress-spinner';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { IsNotReleaseVersion, RXAP_ENVIRONMENT } from '@rxap/environment';
import * as i1$1 from 'rxjs';
import { Subscription, Observable, Subject, EMPTY, ReplaySubject, firstValueFrom, from, isObservable } from 'rxjs';
import { BaseDefinition, RXAP_DEFINITION_METADATA, DefinitionMetadata, DefinitionLoader } from '@rxap/definition';
import { ToggleSubject, CloneObservable } from '@rxap/rxjs';
import { clone, GenerateRandomString, deepMerge, RxapError, isPromiseLike, isPromise } from '@rxap/utilities';
import { tap, finalize, takeUntil, startWith, take, switchMap, map } from 'rxjs/operators';
import { ToMethod } from '@rxap/pattern';

class DataSourceErrorComponent {
    set dataSourceLike(value) {
        this.refresh ??= value.refresh;
        this.retry ??= value.retry;
        this.reset ??= value.reset;
        this.loading ??= value.loading ?? value.loading$;
        this.error ??= value.error ?? value.error$;
    }
    constructor(environment) {
        this.environment = environment;
        this.isNotRelease = false;
        this.errorMessage = signal('Unknown Error');
        this.retryInProgress = signal(false);
        this.resetInProgress = signal(false);
        this.isNotRelease = IsNotReleaseVersion(environment);
    }
    ngOnChanges(changes) {
        if (changes['error']) {
            this.retryInProgress.set(false);
            this.resetInProgress.set(false);
        }
        if (changes['loading']) {
            if (!changes['loading'].currentValue && typeof changes['loading'].currentValue === 'boolean') {
                this.retryInProgress.set(false);
                this.resetInProgress.set(false);
            }
        }
    }
    ngOnDestroy() {
        this._subscription?.unsubscribe();
    }
    ngOnInit() {
        this._subscription = new Subscription();
        if (this.loading instanceof Observable) {
            this._subscription.add(this.loading.subscribe((loading) => {
                if (!loading) {
                    if (this.retryInProgress()) {
                        this.retryInProgress.set(false);
                    }
                    if (this.resetInProgress()) {
                        this.resetInProgress.set(false);
                    }
                }
            }));
        }
        if (this.error instanceof Observable) {
            this._subscription.add(this.error.subscribe((error) => {
                if (error) {
                    this.errorMessage.set(error.message);
                }
            }));
        }
    }
    triggerRetry() {
        if (this.retry) {
            this.retryInProgress.set(true);
            this.retry();
        }
        else if (this.refresh) {
            this.retryInProgress.set(true);
            this.refresh();
        }
    }
    triggerReset() {
        if (this.reset) {
            this.resetInProgress.set(true);
            this.reset();
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceErrorComponent, deps: [{ token: RXAP_ENVIRONMENT }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.1", type: DataSourceErrorComponent, isStandalone: true, selector: "rxap-data-source-error", inputs: { error: "error", refresh: "refresh", retry: "retry", reset: "reset", dataSourceLike: "dataSourceLike", loading: "loading" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"p-10 w-full\">\n  <div class=\"flex flex-col justify-center items-center gap-8\">\n    <span i18n>Something has gone wrong!</span>\n    <div class=\"flex flex-row justify-center items-center gap-4\">\n      <button *ngIf=\"refresh || retry\" type=\"button\" (click)=\"triggerRetry()\" [disabled]=\"retryInProgress() || resetInProgress()\" mat-stroked-button>\n        <span class=\"flex flex-row items-center gap-4\">\n          <span i18n>Retry</span>\n          <mat-spinner *ngIf=\"retryInProgress()\" [diameter]=\"15\"></mat-spinner>\n        </span>\n      </button>\n      <button *ngIf=\"reset\" type=\"button\" (click)=\"triggerReset()\" [disabled]=\"resetInProgress() || retryInProgress()\" mat-stroked-button>\n        <span class=\"flex flex-row items-center gap-4\">\n          <span i18n>Reset</span>\n          <mat-spinner *ngIf=\"resetInProgress()\" [diameter]=\"15\"></mat-spinner>\n        </span>\n      </button>\n    </div>\n    <span *ngIf=\"isNotRelease\" class=\"text-red-700\">{{errorMessage()}}</span>\n  </div>\n</div>\n", styles: [".container{padding:64px;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: "    button[mat-button], button[mat-raised-button], button[mat-flat-button],    button[mat-stroked-button]  ", exportAs: ["matButton"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceErrorComponent, decorators: [{
            type: Component,
            args: [{ selector: 'rxap-data-source-error', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
                        MatButtonModule,
                        NgIf,
                        MatProgressSpinnerModule,
                        JsonPipe,
                    ], template: "<div class=\"p-10 w-full\">\n  <div class=\"flex flex-col justify-center items-center gap-8\">\n    <span i18n>Something has gone wrong!</span>\n    <div class=\"flex flex-row justify-center items-center gap-4\">\n      <button *ngIf=\"refresh || retry\" type=\"button\" (click)=\"triggerRetry()\" [disabled]=\"retryInProgress() || resetInProgress()\" mat-stroked-button>\n        <span class=\"flex flex-row items-center gap-4\">\n          <span i18n>Retry</span>\n          <mat-spinner *ngIf=\"retryInProgress()\" [diameter]=\"15\"></mat-spinner>\n        </span>\n      </button>\n      <button *ngIf=\"reset\" type=\"button\" (click)=\"triggerReset()\" [disabled]=\"resetInProgress() || retryInProgress()\" mat-stroked-button>\n        <span class=\"flex flex-row items-center gap-4\">\n          <span i18n>Reset</span>\n          <mat-spinner *ngIf=\"resetInProgress()\" [diameter]=\"15\"></mat-spinner>\n        </span>\n      </button>\n    </div>\n    <span *ngIf=\"isNotRelease\" class=\"text-red-700\">{{errorMessage()}}</span>\n  </div>\n</div>\n", styles: [".container{padding:64px;width:100%}\n"] }]
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [RXAP_ENVIRONMENT]
                }] }], propDecorators: { error: [{
                type: Input
            }], refresh: [{
                type: Input
            }], retry: [{
                type: Input
            }], reset: [{
                type: Input
            }], dataSourceLike: [{
                type: Input
            }], loading: [{
                type: Input
            }] } });

class BaseDataSource extends BaseDefinition {
    get lastRefreshed() {
        return this._lastRefreshed;
    }
    constructor(metadata = null) {
        super(metadata);
        this.change$ = new Subject();
        /**
         * Indicates weather the data source is currently loading new data
         */
        this.loading$ = EMPTY;
        this.hasError$ = new ToggleSubject();
        this.error$ = new ReplaySubject(1);
        this._lastRefreshed = null;
        this._connectedViewer = new Map();
        this._connectedViewerTeardown = new Map();
        this._data$ = EMPTY;
        /**
         * a map of viewer to view id.
         * Allows to create a view id from the viewer object reference
         * @protected
         */
        this._viewerIds = new Map();
        this._retry$ = new Subject();
    }
    get data() {
        return clone(this._data);
    }
    get hasConnections() {
        return this._connectedViewer.size > 0;
    }
    getViewerId(viewer) {
        if (viewer.id) {
            return viewer.id;
        }
        if (!this._viewerIds.has(viewer)) {
            this._viewerIds.set(viewer, GenerateRandomString());
        }
        return this._viewerIds.get(viewer);
    }
    connect(viewerOrString) {
        let viewer;
        if (typeof viewerOrString === 'string') {
            viewer = { id: viewerOrString };
        }
        else {
            viewer = viewerOrString;
        }
        if (!viewer.id) {
            viewer.id = this.getViewerId(viewer);
        }
        if (this.isConnected(viewer)) {
            return this._connectedViewer.get(viewer.id);
        }
        if (!viewer.viewChange) {
            viewer.viewChange = EMPTY;
        }
        const _connection = this._connect(viewer);
        let connection;
        let teardownLogic = null;
        if (Array.isArray(_connection)) {
            if (_connection.length !== 2) {
                throw new Error('if this._connect returns an array. The array should have two items');
            }
            connection = _connection[0];
            teardownLogic = _connection[1];
        }
        else {
            connection = _connection;
        }
        const destroy$ = new Subject();
        const cacheKey = ['rxap', 'data-source', this.constructor.name, this.id].join('_');
        const restore = viewer.restore ?? this.metadata.restore ?? false;
        connection = connection.pipe(tap((data) => {
            this._data = data;
            if (restore) {
                try {
                    const cache = JSON.stringify(data);
                    localStorage.setItem(cacheKey, cache);
                }
                catch (e) {
                    console.warn(`Failed to store data source '${this.id}' data in local storage`);
                }
            }
        }), tap((data) => this.change$.next(data)), tap(() => this._lastRefreshed = new Date()), finalize(() => this.disconnect(viewer)), takeUntil(destroy$));
        if (restore) {
            const data = localStorage.getItem(cacheKey);
            if (data) {
                this._data = JSON.parse(data);
                connection = connection.pipe(startWith(this._data));
            }
        }
        this._connectedViewer.set(viewer.id, connection);
        if (teardownLogic) {
            const tl = teardownLogic;
            teardownLogic = () => {
                destroy$.next();
                if (typeof tl === 'function') {
                    tl();
                }
                else {
                    tl.unsubscribe();
                }
            };
        }
        else {
            teardownLogic = () => {
                destroy$.next();
            };
        }
        this._connectedViewerTeardown.set(viewer.id, teardownLogic);
        return connection;
    }
    attach(viewerId) {
        if (this.isConnected(viewerId)) {
            return CloneObservable(this._connectedViewer.get(viewerId));
        }
        throw new Error(`No active connection with viewer id '${viewerId}' found`);
    }
    isConnected(viewerOrId) {
        const viewerId = typeof viewerOrId === 'string'
            ? viewerOrId
            : viewerOrId.id ?? this.getViewerId(viewerOrId);
        return this._connectedViewer.has(viewerId);
    }
    disconnect(viewerOrId) {
        const viewerId = typeof viewerOrId === 'string'
            ? viewerOrId
            : viewerOrId.id ?? this.getViewerId(viewerOrId);
        if (this.isConnected(viewerId)) {
            this._disconnect(viewerId);
            this._connectedViewer.delete(viewerId);
            if (this._connectedViewerTeardown.has(viewerId)) {
                const teardownLogic = this._connectedViewerTeardown.get(viewerId);
                if (teardownLogic) {
                    if (typeof teardownLogic === 'function') {
                        teardownLogic();
                    }
                    else {
                        teardownLogic.unsubscribe();
                    }
                }
            }
        }
        else {
            console.warn(`Connection with viewer id '${viewerId}' is not connected to the data source '${this.id}'`);
        }
        // TODO : find better cleanup solution
        if (typeof viewerOrId === 'string') {
            for (const [viewer, id] of this._viewerIds.entries()) {
                if (viewerOrId === id) {
                    this._viewerIds.delete(viewer);
                }
            }
        }
        else {
            this._viewerIds.delete(viewerOrId);
        }
    }
    /**
     * Creates a connection to tha data source and converts the Observable into a
     * promise and then disconnects the viewer
     */
    async toPromise(viewer) {
        const result = await firstValueFrom(this.connect(viewer).pipe(take(1)));
        this.disconnect(viewer);
        return result;
    }
    derive(id, metadata = this.metadata) {
        return new BaseDataSource({
            ...deepMerge(this.metadata, metadata),
            id,
        });
    }
    toJSON() {
        return {
            id: this.id,
            metadata: this.metadata,
            connected: this._connectedViewer.keys(),
            data: this._data,
        };
    }
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    refresh() {
    }
    retry() {
        this._retry$.next();
    }
    reset() {
        for (const viewerId of this._connectedViewer.keys()) {
            this.disconnect(viewerId);
        }
        // eslint-disable-next-line no-prototype-builtins
        if (this.metadata.hasOwnProperty('context')) {
            delete this.metadata['context'];
        }
    }
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    _disconnect(viewerId) {
    }
    genericRetryFunction(error, retryCount) {
        return this._retry$.asObservable().pipe(tap(() => this.hasError$.disable()));
    }
    handelError(error) {
        if (isDevMode()) {
            console.log(`DataSource '${this.id}' has an error:`, error);
        }
    }
    _connect(viewer) {
        this.init();
        return this._data$;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseDataSource, deps: [{ token: RXAP_DEFINITION_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseDataSource, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [RXAP_DEFINITION_METADATA]
                }] }] });
function RxapDataSource(dataSourceIdOrMetadata, className = 'BaseDataSource', packageName = '@rxap/data-source') {
    return function (target) {
        DefinitionMetadata(dataSourceIdOrMetadata, className, packageName)(target);
    };
}

class DataSourceLoader extends DefinitionLoader {
    connect(dataSourceIdOrInstanceOrToken, viewer, metadata, injector, notFoundValue, flags) {
        return this
            .load(dataSourceIdOrInstanceOrToken, metadata, injector, notFoundValue, flags)
            .connect(viewer);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceLoader, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceLoader, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceLoader, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

function DataSourceRefreshToMethodAdapterFactory(dataSource) {
    return ToMethod(() => dataSource.refresh());
}

class RxapDataSourceError extends RxapError {
    constructor(message, code, className) {
        super('@rxap/data-source', message, code, className);
    }
}

const RXAP_STATIC_DATA_SOURCE_DATA = new InjectionToken('rxap/data-source/static-data-source-data');
const RXAP_DATA_SOURCE_REFRESH = new InjectionToken('rxap/data-source/refresh');
const RXAP_OBSERVABLE_DATA_SOURCE = new InjectionToken('rxap/data-source/observable-data-source');
const RXAP_DATA_SOURCE_METADATA = new InjectionToken('rxap/data-source/metadata');
const RXAP_DATA_SOURCE = new InjectionToken('rxap/data-source/instance');
const RXAP_PIPE_DATA_SOURCE_OPERATOR = new InjectionToken('rxap/data-source/pipe-operator');
const RXAP_DATA_SOURCE_METHOD = new InjectionToken('rxap/data-source/method');
const RXAP_DATA_SOURCE_METHOD_WITHOUT_PARAMETERS = new InjectionToken('rxap/data-source/method-without-parameters', {
    providedIn: 'root',
    factory: () => false,
});

class MethodDataSource extends BaseDataSource {
    constructor(method, withoutParameters = false) {
        super(method.metadata);
        this.method = method;
        this.withoutParameters = withoutParameters;
        this._data$ = new ReplaySubject(1);
        this.loading$ = new ToggleSubject(false);
        this._refresh = new Subject();
    }
    ngOnInit() {
        if (this.withoutParameters) {
            this.executeWithoutParameters();
        }
    }
    refresh() {
        this._refresh.next();
        if (this.withoutParameters) {
            this.executeWithoutParameters();
        }
    }
    _connect(viewer) {
        if (this.withoutParameters) {
            return super._connect(viewer);
        }
        else {
            return this._refresh.pipe(tap(() => this.hasError$.disable()), startWith(undefined), switchMap(() => {
                if (viewer.viewChange && viewer.viewChange !== EMPTY) {
                    return viewer.viewChange.pipe(tap(() => this.loading$.enable()), switchMap((parameters) => from(this.execute(parameters)).pipe(this.handelExecution())));
                }
                else {
                    this.loading$.enable();
                    return from(this.execute(viewer)).pipe(this.handelExecution());
                }
            }));
        }
    }
    handelExecution() {
        return tap({
            next: () => {
                this.loading$.disable();
            },
            error: (error) => {
                this.loading$.disable();
                this.hasError$.enable();
                this.error$.next(error);
            },
            finalize: () => {
                this.loading$.disable();
            }
        });
    }
    async execute(parameters) {
        return this.method.call(parameters);
    }
    async executeWithoutParameters() {
        this.hasError$.disable();
        this.loading$.enable();
        await firstValueFrom(from(this.execute()).pipe(this.handelExecution(), tap({
            next: (data) => this._data$.next(data),
        })));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: MethodDataSource, deps: [{ token: RXAP_DATA_SOURCE_METHOD }, { token: RXAP_DATA_SOURCE_METHOD_WITHOUT_PARAMETERS }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: MethodDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: MethodDataSource, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [RXAP_DATA_SOURCE_METHOD]
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [RXAP_DATA_SOURCE_METHOD_WITHOUT_PARAMETERS]
                }] }] });

class ObservableDataSource extends BaseDataSource {
    constructor(observable, metadata = null) {
        super(metadata);
        if (observable) {
            this._data$ = observable;
        }
        else if (this.metadata.data) {
            this._data$ = this.metadata.data;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: ObservableDataSource, deps: [{ token: RXAP_OBSERVABLE_DATA_SOURCE, optional: true }, { token: RXAP_DATA_SOURCE_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: ObservableDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: ObservableDataSource, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.Observable, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [RXAP_OBSERVABLE_DATA_SOURCE]
                }] }, { type: undefined, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [RXAP_DATA_SOURCE_METADATA]
                }] }] });
function RxapObservableDataSource(metadata, className = 'ObservableDataSource', packageName = '@rxap/data-source') {
    return function (target) {
        RxapDataSource(metadata, className, packageName)(target);
    };
}
function observableDataSource(data, metadata = { id: 'static' }) {
    return new ObservableDataSource(data, metadata);
}

function RxapPipeDataSource(metadata, className = 'PipeDataSource', packageName = '@rxap/data-source') {
    return function (target) {
        RxapDataSource(metadata, className, packageName)(target);
    };
}
class PipeDataSource extends BaseDataSource {
    constructor(dataSource, operation = null, ...operations) {
        super(dataSource.metadata);
        this.dataSource = dataSource;
        this._refresh = new Subject();
        this._operations = [];
        this.loading$ = this.dataSource.loading$;
        if (operation) {
            this.setOperations(operation, ...operations.filter(op => typeof op === 'function'));
            if (operations.some(op => typeof op !== 'function')) {
                this.metadata = {
                    ...this.metadata,
                    ...operations.find(op => typeof op !== 'function'),
                };
            }
        }
    }
    get operations() {
        return this._operations;
    }
    setOperations(operation, ...operations) {
        if (this._initialised) {
            throw new RxapDataSourceError('Can not set operations after the data source is initialised', '', 'PipeDataSource');
        }
        this._operations = [operation, ...operations];
    }
    ngOnDestroy() {
        super.ngOnDestroy();
        this.dataSource.disconnect(this.metadata);
    }
    /**
     * @param parent true - call the refresh method of the parent data source
     */
    refresh(parent = this.metadata['refreshParent'] ?? false) {
        if (parent) {
            this.dataSource.refresh();
        }
        else {
            this._refresh.next();
        }
    }
    reset() {
        return this.dataSource.reset();
    }
    toJSON() {
        return {
            ...super.toJSON(),
            dataSource: this.dataSource,
        };
    }
    _connect(viewer) {
        this.init();
        return [
            this.dataSource.connect(viewer).pipe(switchMap(data => this._refresh.pipe(startWith(null), map(() => data))), 
            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
            // @ts-ignore
            ...this.viewerToOperations(viewer)),
            () => this.dataSource.disconnect(viewer),
        ];
    }
    viewerToOperations(viewer) {
        return this.operations;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: PipeDataSource, deps: [{ token: RXAP_DATA_SOURCE }, { token: RXAP_PIPE_DATA_SOURCE_OPERATOR, optional: true }, { token: Array }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: PipeDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: PipeDataSource, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: BaseDataSource, decorators: [{
                    type: Inject,
                    args: [RXAP_DATA_SOURCE]
                }] }, { type: undefined, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [RXAP_PIPE_DATA_SOURCE_OPERATOR]
                }] }, { type: Array }] });
function pipeDataSource(dataSource, operation, ...operations) {
    return new PipeDataSource(dataSource, operation, ...operations);
}

class StaticDataSource extends BaseDataSource {
    constructor(data, metadata) {
        super(metadata);
        this._data$ = new ReplaySubject(1);
        if ((data === undefined || data === null) && this.metadata.data !== undefined) {
            data = this.metadata.data;
        }
        if (data === undefined) {
            throw new RxapDataSourceError(`Can not create static data source '${this.id}' with undefined as data`, '');
        }
        if (isObservable(data)) {
            this._dataSubscription = data.pipe(tap({
                next: data => this._data$.next(data),
                error: error => this.error$.next(error),
            })).subscribe();
        }
        else if (isPromiseLike(data)) {
            if (isPromise(data)) {
                data.then(data => this._data$.next(data)).catch((error) => this.error$.next(error));
            }
            else {
                data.then(data => this._data$.next(data));
            }
        }
        else if (typeof data === 'function') {
            // TODO : fix typeof function cast
            this._data$.next((this._data = data()));
        }
        else {
            this._data$.next((this._data = data));
        }
    }
    get data() {
        return clone(this._data);
    }
    set data(value) {
        const data = clone(value);
        this._data = data;
        this._data$.next(data);
    }
    ngOnDestroy() {
        super.ngOnDestroy();
        this._dataSubscription?.unsubscribe();
    }
    _connect() {
        this.init();
        return this._data$.asObservable();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: StaticDataSource, deps: [{ token: RXAP_STATIC_DATA_SOURCE_DATA, optional: true }, { token: RXAP_DATA_SOURCE_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: StaticDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: StaticDataSource, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [RXAP_STATIC_DATA_SOURCE_DATA]
                }] }, { type: undefined, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [RXAP_DATA_SOURCE_METADATA]
                }] }] });
function RxapStaticDataSource(metadata, className = 'StaticDataSource', packageName = '@rxap/data-source') {
    return function (target) {
        RxapDataSource(metadata, className, packageName)(target);
    };
}
function staticDataSource(data, metadata = { id: 'static' }) {
    return new StaticDataSource(data, metadata);
}

// region data-source-error
// endregion

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

export { BaseDataSource, DataSourceErrorComponent, DataSourceLoader, DataSourceRefreshToMethodAdapterFactory, MethodDataSource, ObservableDataSource, PipeDataSource, RXAP_DATA_SOURCE, RXAP_DATA_SOURCE_METADATA, RXAP_DATA_SOURCE_METHOD, RXAP_DATA_SOURCE_METHOD_WITHOUT_PARAMETERS, RXAP_DATA_SOURCE_REFRESH, RXAP_OBSERVABLE_DATA_SOURCE, RXAP_PIPE_DATA_SOURCE_OPERATOR, RXAP_STATIC_DATA_SOURCE_DATA, RxapDataSource, RxapDataSourceError, RxapObservableDataSource, RxapPipeDataSource, RxapStaticDataSource, StaticDataSource, observableDataSource, pipeDataSource, staticDataSource };
//# sourceMappingURL=rxap-data-source.mjs.map
