//#region src/extensions/typed-event-bus.ts
/**
* Type-safe event bus for inter-extension communication
*
* @example
* ```typescript
* interface MyEvents {
*   'user:login': { userId: string; timestamp: number };
*   'message:received': { chatId: string; content: string };
* }
*
* interface MyRequests {
*   'user:get': { userId: string };
* }
*
* interface MyResponses {
*   'user:get': { name: string; email: string };
* }
*
* const bus = new TypedEventBus<MyEvents, MyRequests, MyResponses>();
*
* // Listen for events
* bus.on('user:login', (data) => {
*   console.log(`User ${data.userId} logged in`);
* });
*
* // Emit events
* bus.emit('user:login', { userId: 'user123', timestamp: Date.now() });
*
* // Request-response
* bus.onRequest('user:get', async (params) => {
*   return { name: 'John', email: 'john@example.com' };
* });
*
* const user = await bus.request('user:get', { userId: 'user123' });
* ```
*/
var TypedEventBus = class {
	eventHandlers = /* @__PURE__ */ new Map();
	wildcardHandlers = [];
	requestHandlers = /* @__PURE__ */ new Map();
	pendingRequests = /* @__PURE__ */ new Map();
	options;
	requestIdCounter = 0;
	constructor(options = {}) {
		this.options = {
			requestTimeout: options.requestTimeout ?? 5e3,
			catchErrors: options.catchErrors ?? true,
			logger: options.logger ?? this.createDefaultLogger()
		};
	}
	/**
	* Subscribe to an event
	*
	* @param event - Event name
	* @param handler - Event handler function
	* @param options - Handler options (extensionId, once)
	* @returns Unsubscribe function
	*/
	on(event, handler, options = {}) {
		const meta = {
			handler,
			extensionId: options.extensionId,
			once: options.once
		};
		const handlers = this.eventHandlers.get(event) || [];
		handlers.push(meta);
		this.eventHandlers.set(event, handlers);
		return () => {
			this.off(event, handler);
		};
	}
	/**
	* Unsubscribe from an event
	*
	* @param event - Event name
	* @param handler - Handler to remove
	*/
	off(event, handler) {
		const handlers = this.eventHandlers.get(event);
		if (!handlers) return;
		const index = handlers.findIndex((h) => h.handler === handler);
		if (index >= 0) {
			handlers.splice(index, 1);
			if (handlers.length === 0) this.eventHandlers.delete(event);
		}
	}
	/**
	* Emit an event
	*
	* @param event - Event name
	* @param data - Event data
	*/
	emit(event, data) {
		const handlers = this.eventHandlers.get(event);
		if (handlers) {
			const handlersToRemove = [];
			handlers.forEach((meta, index) => {
				try {
					meta.handler(data);
					if (meta.once) handlersToRemove.push(index);
				} catch (error) {
					this.handleError(`Error in event handler for ${String(event)}`, error);
				}
			});
			for (let i = handlersToRemove.length - 1; i >= 0; i--) handlers.splice(handlersToRemove[i], 1);
			if (handlers.length === 0) this.eventHandlers.delete(event);
		}
		this.wildcardHandlers.forEach((meta) => {
			if (this.matchWildcard(meta.pattern, String(event))) try {
				meta.handler(data, String(event));
			} catch (error) {
				this.handleError(`Error in wildcard handler for ${String(event)}`, error);
			}
		});
	}
	/**
	* Subscribe to events matching a wildcard pattern
	*
	* @param pattern - Wildcard pattern (e.g., 'user:*', '*:update')
	* @param handler - Handler function
	* @param options - Handler options (extensionId)
	* @returns Unsubscribe function
	*/
	onWildcard(pattern, handler, options = {}) {
		const meta = {
			handler,
			pattern,
			extensionId: options.extensionId
		};
		this.wildcardHandlers.push(meta);
		return () => {
			const index = this.wildcardHandlers.findIndex((h) => h.handler === handler);
			if (index >= 0) this.wildcardHandlers.splice(index, 1);
		};
	}
	/**
	* Check if an event matches a wildcard pattern
	*/
	matchWildcard(pattern, event) {
		if (pattern === "*") return true;
		const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
		return new RegExp(`^${regexPattern}$`).test(event);
	}
	/**
	* Register a request handler
	*/
	onRequest(method, handler, options = {}) {
		const meta = {
			handler,
			extensionId: options.extensionId
		};
		const handlers = this.requestHandlers.get(method) || [];
		handlers.push(meta);
		this.requestHandlers.set(method, handlers);
	}
	/**
	* Make a request and wait for response
	*/
	async request(method, params, _options = {}) {
		const handlers = this.requestHandlers.get(method);
		if (!handlers || handlers.length === 0) throw new Error(`No handler registered for request: ${String(method)}`);
		for (const meta of handlers) try {
			const result = await meta.handler(params);
			if (result !== null && result !== void 0) return result;
		} catch (error) {
			this.handleError(`Error in request handler for ${String(method)}`, error);
			throw error;
		}
		throw new Error(`All handlers returned null for request: ${String(method)}`);
	}
	/**
	* Remove all listeners and handlers for a specific extension
	*
	* @param extensionId - Extension ID to cleanup
	*/
	cleanup(extensionId) {
		for (const [event, handlers] of this.eventHandlers.entries()) {
			const filtered = handlers.filter((h) => h.extensionId !== extensionId);
			if (filtered.length === 0) this.eventHandlers.delete(event);
			else this.eventHandlers.set(event, filtered);
		}
		this.wildcardHandlers = this.wildcardHandlers.filter((h) => h.extensionId !== extensionId);
		for (const [method, handlers] of this.requestHandlers.entries()) {
			const filtered = handlers.filter((h) => h.extensionId !== extensionId);
			if (filtered.length === 0) this.requestHandlers.delete(method);
			else this.requestHandlers.set(method, filtered);
		}
	}
	cleanupAll() {
		this.eventHandlers.clear();
		this.wildcardHandlers = [];
		this.requestHandlers.clear();
		for (const req of this.pendingRequests.values()) req.reject(/* @__PURE__ */ new Error("EventBus cleanup"));
		this.pendingRequests.clear();
	}
	/**
	* Get number of active event handlers for an event
	*/
	listenerCount(event) {
		return this.eventHandlers.get(event)?.length || 0;
	}
	/**
	* Get all registered event names
	*/
	eventNames() {
		return Array.from(this.eventHandlers.keys());
	}
	/**
	* Remove all listeners (use with caution)
	*/
	removeAllListeners() {
		this.eventHandlers.clear();
		this.wildcardHandlers = [];
		this.requestHandlers.clear();
		for (const request of this.pendingRequests.values()) {
			if (request.timer) clearTimeout(request.timer);
			request.reject(/* @__PURE__ */ new Error("EventBus destroyed"));
		}
		this.pendingRequests.clear();
	}
	handleError(message, error) {
		if (this.options.catchErrors) this.options.logger.error(`${message}: ${error instanceof Error ? error.message : String(error)}`);
		else throw error;
	}
	createDefaultLogger() {
		return {
			debug: () => {},
			info: () => {},
			warn: console.warn,
			error: console.error
		};
	}
};
//#endregion
export { TypedEventBus };

//# sourceMappingURL=typed-event-bus.js.map