import { UMB_MANAGEMENT_API_SERVER_EVENT_CONTEXT } from './server-event.context-token.js';
import { UmbContextBase } from '../../../../libs/class-api/index.js';
import { UMB_AUTH_CONTEXT } from '../../../core/auth/index.js';
import { HubConnectionBuilder } from '../../../../external/signalr/index.js';
import { UMB_SERVER_CONTEXT } from '../../../core/server/index.js';
import { filter, Subject } from '../../../../external/rxjs/index.js';
import { UmbBooleanState } from '../../../../libs/observable-api/index.js';
export class UmbManagementApiServerEventContext extends UmbContextBase {
    #connection;
    #authContext;
    #serverContext;
    #events;
    #isConnected;
    /**
     * Filters events by the given event types
     * @param {string} eventTypes - The event types to filter by
     * @returns {Observable<UmbManagementApiServerEventModel>} - The filtered events
     * @memberof UmbManagementApiServerEventContext
     */
    byEventSource(eventTypes) {
        return this.#events.asObservable().pipe(filter((event) => event.eventType === eventTypes));
    }
    /**
     * Filters events by the given event sources and event types
     * @param {Array<string>} eventSources - The event sources to filter by
     * @param {Array<string>} eventTypes - The event types to filter by
     * @returns {Observable<UmbManagementApiServerEventModel>} - The filtered events
     * @memberof UmbManagementApiServerEventContext
     */
    byEventSourcesAndEventTypes(eventSources, eventTypes) {
        return this.#events
            .asObservable()
            .pipe(filter((event) => eventSources.includes(event.eventSource) && eventTypes.includes(event.eventType)));
    }
    constructor(host) {
        super(host, UMB_MANAGEMENT_API_SERVER_EVENT_CONTEXT);
        this.#events = new Subject();
        this.events = this.#events.asObservable();
        this.#isConnected = new UmbBooleanState(undefined);
        this.isConnected = this.#isConnected.asObservable();
        this.consumeContext(UMB_AUTH_CONTEXT, (context) => {
            this.#authContext = context;
            this.#observeIsAuthorized();
        });
        this.consumeContext(UMB_SERVER_CONTEXT, (context) => {
            this.#serverContext = context;
            this.#observeIsAuthorized();
        });
    }
    #observeIsAuthorized() {
        if (!this.#authContext || !this.#serverContext)
            return;
        this.observe(this.#authContext.isAuthorized, (isAuthorized) => {
            if (isAuthorized === undefined)
                return;
            if (isAuthorized) {
                this.#initHubConnection('[redacted]');
            }
            else {
                this.#isConnected.setValue(false);
                this.#connection?.stop();
                this.#connection = undefined;
            }
        });
    }
    #initHubConnection(token) {
        const serverURL = this.#serverContext?.getServerUrl();
        if (!serverURL) {
            throw new Error('Server URL is not defined in the server context');
        }
        // TODO: get the url from a server config?
        const serverEventHubUrl = `${serverURL}/umbraco/serverEventHub`;
        this.#connection = new HubConnectionBuilder()
            .withUrl(serverEventHubUrl, {
            accessTokenFactory: () => token,
        })
            .build();
        this.#connection.on('notify', (payload) => {
            const event = {
                ...payload,
                clientTimestamp: new Date().toISOString(),
            };
            this.#events.next(event);
        });
        this.#connection
            .start()
            .then(() => this.#isConnected.setValue(true))
            .catch(() => this.#isConnected.setValue(false));
        this.#connection.onclose(() => this.#isConnected.setValue(false));
    }
}
export { UmbManagementApiServerEventContext as api };
