import { createBackendManager } from "./BackendManager";
import { createServiceManager } from "./ServiceManager";
import { createArticleState } from "./ArticleState";
import { createArticleQuery } from "./ArticleQuery";
import { createArticleManager } from "./ArticleManager";
import { createNotificationCenter } from "./NotificationCenter";
import { createConnectionManager } from "./ConnectionManager";
import { createArticleRegistry } from "./ArticleRegistry";
import { createProjectManager } from "./ProjectManager";
import { createOperationResultHandler } from "./OperationResultHandler";
import { createHooks } from "./Hooks";
import { createSourceRegistry } from "./SourceRegistry";
import { createLocalizationManager, } from "./LocalizationManager";
import { NoopApplicationState } from "./NoopApplicationState";
import { createApplicationStateManager } from "./ApplicationStateManager";
import { createScheduler } from "./Scheduler";
export const BackendRegistry = createBackendManager();
export const createSession = (params = {}) => {
    const services = createServices(params);
    return createSessionAPI(services);
};
export const createServices = ({ language, currency, locale, applicationState = NoopApplicationState, }) => {
    const hooks = createHooks();
    const connectionManager = createConnectionManager();
    const notificationCenter = createNotificationCenter();
    const localizationManager = createLocalizationManager({
        language,
        currency,
        locale,
    }, notificationCenter);
    const serviceManager = createServiceManager(BackendRegistry);
    const articleState = createArticleState();
    const articleQuery = createArticleQuery(articleState);
    const scheduler = createScheduler(articleQuery);
    const articleRegistry = createArticleRegistry(serviceManager, articleState);
    const operationResultHandler = createOperationResultHandler(articleRegistry, articleQuery, notificationCenter, hooks);
    const articleManager = createArticleManager(serviceManager, articleState, articleQuery, operationResultHandler, applicationState);
    const sourceRegistry = createSourceRegistry(serviceManager, articleQuery, scheduler);
    const projectManager = createProjectManager(serviceManager, articleQuery, articleManager, operationResultHandler, hooks, sourceRegistry, connectionManager, localizationManager);
    return {
        localizationManager,
        operationResultHandler,
        hooks,
        scheduler,
        notificationCenter,
        backendManager: BackendRegistry,
        serviceManager,
        articleState,
        articleQuery,
        articleManager,
        connectionManager,
        articleRegistry,
        projectManager,
        sourceRegistry,
        applicationState,
    };
};
export const createSessionAPI = (services) => {
    const applicationStateManager = createApplicationStateManager(services.applicationState, services.hooks, services.notificationCenter);
    const destroy = async () => {
        applicationStateManager.destroy();
        services.notificationCenter.destroy();
        await services.hooks.beforeDestroy.emit();
        await services.connectionManager.closeAllConnections();
    };
    const reset = async () => {
        await services.articleManager.deleteArticles(services.articleQuery.getAllComIds());
    };
    return {
        ...services.articleQuery,
        ...services.serviceManager,
        ...services.articleManager,
        ...services.serviceManager,
        ...services.connectionManager,
        ...services.projectManager,
        ...BackendRegistry,
        ...services.operationResultHandler,
        ...services.sourceRegistry,
        ...services.localizationManager,
        hooks: services.hooks,
        scheduleArticleOperation: services.scheduler.queueOperation,
        getApplicationState: services.applicationState.getState.bind(services.applicationState),
        getApplicationStateValue: services.applicationState.getValue.bind(services.applicationState),
        setApplicationState: services.applicationState.setState.bind(services.applicationState),
        setApplicationStateValue: services.applicationState.setValue.bind(services.applicationState),
        destroy,
        sendNotification: services.notificationCenter.send,
        subscribe: services.notificationCenter.subscribe,
        onAnyEvent: services.notificationCenter.any,
        on: services.notificationCenter.on,
        unsubscribe: services.notificationCenter.unsubscribe,
        reset,
    };
};
