"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventService = void 0;
const events_1 = require("events");
function defaultConsoleLogHandler(event) {
    const prefix = event.source ? `[${event.source}] ` : "";
    const line = `${prefix}${event.message}\n`;
    switch (event.level) {
        case "warn":
            process.stderr.write(line);
            break;
        case "error":
            process.stderr.write(line);
            break;
        default:
            process.stdout.write(line);
    }
}
class EventService extends events_1.EventEmitter {
    blockingHandlers = new Map();
    managedListeners = new Map();
    defaultLoggerActive = true;
    boundDefaultLogHandler = defaultConsoleLogHandler;
    eventTypes = {
        agentMsg: "agent:msg",
        agentsRegister: "agents:register",
        agentsCall: "agents:call",
        pluginLog: "plugin:log",
    };
    constructor() {
        super();
        this.setMaxListeners(100);
        this.on(this.eventTypes.pluginLog, this.boundDefaultLogHandler);
    }
    suppressDefaultLogger() {
        if (this.defaultLoggerActive) {
            this.removeListener(this.eventTypes.pluginLog, this.boundDefaultLogHandler);
            this.defaultLoggerActive = false;
        }
    }
    restoreDefaultLogger() {
        if (!this.defaultLoggerActive) {
            this.on(this.eventTypes.pluginLog, this.boundDefaultLogHandler);
            this.defaultLoggerActive = true;
        }
    }
    onBlocking(event, handler) {
        if (!this.blockingHandlers.has(event)) {
            this.blockingHandlers.set(event, []);
        }
        this.blockingHandlers.get(event).push({ handler });
    }
    offBlocking(event, handler) {
        const handlers = this.blockingHandlers.get(event);
        if (!handlers)
            return;
        const filtered = handlers.filter((entry) => entry.handler !== handler);
        if (filtered.length === 0) {
            this.blockingHandlers.delete(event);
            return;
        }
        this.blockingHandlers.set(event, filtered);
    }
    setListener(spec, handler) {
        const { key, event, once = false, blocking = false } = spec;
        this.removeManagedListener(key);
        let wrappedHandler;
        if (once) {
            wrappedHandler = (...args) => {
                try {
                    handler(...args);
                }
                finally {
                    this.managedListeners.delete(key);
                }
            };
        }
        else {
            wrappedHandler = handler;
        }
        const record = {
            key,
            event,
            handler,
            wrappedHandler,
            once,
            blocking,
        };
        if (blocking) {
            if (!this.blockingHandlers.has(event)) {
                this.blockingHandlers.set(event, []);
            }
            this.blockingHandlers.get(event).push({ handler: wrappedHandler });
        }
        else {
            if (once) {
                super.once(event, wrappedHandler);
            }
            else {
                super.on(event, wrappedHandler);
            }
        }
        this.managedListeners.set(key, record);
    }
    removeManagedListener(key) {
        const existing = this.managedListeners.get(key);
        if (!existing)
            return;
        if (existing.blocking) {
            this.offBlocking(existing.event, existing.wrappedHandler);
        }
        else {
            super.removeListener(existing.event, existing.wrappedHandler);
        }
        this.managedListeners.delete(key);
    }
    removeManagedListenersByPrefix(prefix) {
        for (const key of Array.from(this.managedListeners.keys())) {
            if (key.startsWith(prefix)) {
                this.removeManagedListener(key);
            }
        }
    }
    clearManagedListeners() {
        for (const key of Array.from(this.managedListeners.keys())) {
            this.removeManagedListener(key);
        }
    }
    hasManagedListener(key) {
        return this.managedListeners.has(key);
    }
    async emitBlocking(event, ...args) {
        const results = [];
        const handlers = this.blockingHandlers.get(event) || [];
        for (const { handler } of handlers) {
            try {
                const result = handler(...args);
                results.push(result instanceof Promise ? await result : result);
            }
            catch (error) {
                throw error;
            }
        }
        this.emit(event, ...args);
        return results.filter((r) => Boolean(r));
    }
    async emitNonBlocking(event, ...args) {
        const handlers = this.blockingHandlers.get(event) || [];
        const results = [];
        for (const { handler } of handlers) {
            try {
                const result = handler(...args);
                results.push(result instanceof Promise ? await result : result);
            }
            catch (error) {
                console.error(`Non-blocking handler error for event '${event}':`, error);
            }
        }
        this.emit(event, ...args);
        return results.filter((r) => Boolean(r));
    }
    registerAgent(agent) {
        this.emit(this.eventTypes.agentsRegister, { name: agent.name, agent });
    }
    callAgent(name, query) {
        return new Promise((resolve, reject) => {
            this.emit(this.eventTypes.agentsCall, { name, query, resolve, reject });
        });
    }
    log(source, message, level = "info") {
        this.emit(this.eventTypes.pluginLog, {
            source,
            message,
            level,
            timestamp: Date.now(),
        });
    }
}
exports.EventService = EventService;
//# sourceMappingURL=EventService.js.map