"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Engine = void 0;
const inversify_1 = require("inversify");
const config_js_1 = require("../config.js");
const logger_js_1 = require("../logger.js");
const services_1 = require("./services");
const playwright_js_1 = require("./services/playwright.js");
const session_js_1 = require("./session.js");
(0, inversify_1.decorate)((0, inversify_1.injectable)(), logger_js_1.ConsoleLogger);
(0, inversify_1.decorate)((0, inversify_1.injectable)(), config_js_1.EnvConfiguration);
class Engine {
    constructor() {
        this.container = new inversify_1.Container({ skipBaseClassChecks: true });
        this.container.bind(Engine).toConstantValue(this);
        this.container.bind(logger_js_1.Logger).to(logger_js_1.ConsoleLogger).inSingletonScope();
        this.container.bind(config_js_1.Configuration).to(config_js_1.EnvConfiguration).inSingletonScope();
        this.container.bind(services_1.ApiRequest).toSelf().inSingletonScope();
        this.container.bind(services_1.BlobService).toSelf().inSingletonScope();
        this.container.bind(services_1.BrowserService).toSelf().inSingletonScope();
        this.container.bind(services_1.CheckpointService).toSelf().inSingletonScope();
        this.container.bind(services_1.CredentialsService).toSelf().inSingletonScope();
        this.container.bind(services_1.EmulationService).toSelf().inSingletonScope();
        this.container.bind(services_1.FetchService).toSelf().inSingletonScope();
        this.container.bind(services_1.FlowService).toSelf().inSingletonScope();
        this.container.bind(services_1.GlobalsService).toSelf().inSingletonScope();
        this.container.bind(services_1.HttpCallbackService).toSelf().inSingletonScope();
        this.container.bind(services_1.ProxyService).toSelf().inSingletonScope();
        this.container.bind(services_1.RegistryService).toSelf().inSingletonScope();
        this.container.bind(services_1.ReporterService).toSelf().inSingletonScope();
        this.container.bind(services_1.ResolverService).toSelf().inSingletonScope();
        this.container.bind(services_1.UserAgentService).toSelf().inSingletonScope();
        this.container.bind(playwright_js_1.PlaywrightService).toSelf().inSingletonScope();
    }
    get(serviceIdentifier) {
        return this.container.get(serviceIdentifier);
    }
    get $logger() {
        return this.container.get(logger_js_1.Logger);
    }
    get $resolver() {
        return this.container.get(services_1.ResolverService);
    }
    addExtension(extension) {
        return this.get(services_1.ResolverService).addExtension(extension);
    }
    removeExtension(extension) {
        this.get(services_1.ResolverService).removeExtension(extension);
    }
    async startSession() {
        const promises = this.resolveSessionHandlers().map(async (service) => {
            try {
                if (service.onSessionStart) {
                    await service.onSessionStart();
                }
            }
            catch (error) {
                this.$logger.error('onSessionStart handler failed', {
                    serviceName: service.constructor.name,
                    error,
                });
            }
        });
        await Promise.all(promises);
    }
    async finishSession() {
        const promises = this.resolveSessionHandlers().map(async (service) => {
            try {
                if (service.onSessionFinish) {
                    await service.onSessionFinish();
                }
            }
            catch (error) {
                this.$logger.error('onSessionFinish handler failed', {
                    serviceName: service.constructor.name,
                    error,
                });
            }
        });
        await Promise.all(promises);
    }
    resolveSessionHandlers() {
        const services = [];
        for (const handler of session_js_1.sessionHandlers) {
            const service = this.findBinding(handler);
            if (service) {
                services.push(service);
            }
        }
        return services;
    }
    getAllBindings() {
        const map = this.container._bindingDictionary._map;
        const bindings = [...map.values()];
        return bindings.flat();
    }
    findBinding(serviceIdentifier) {
        if (this.container.isBound(serviceIdentifier)) {
            return this.container.get(serviceIdentifier);
        }
        const resolver = this.get(services_1.ResolverService);
        for (const ext of resolver.getExtensions()) {
            if (ext.isInitialized()) {
                if (ext.container.isBound(serviceIdentifier)) {
                    return ext.container.get(serviceIdentifier);
                }
            }
        }
        return null;
    }
    cleanupUnusedSessionHandlers() {
        for (const handler of session_js_1.sessionHandlers) {
            const service = this.findBinding(handler);
            if (!service) {
                session_js_1.sessionHandlers.delete(handler);
            }
        }
    }
}
exports.Engine = Engine;
//# sourceMappingURL=engine.js.map