import { writable, get } from 'svelte/store'; import { MudConnection } from './MudConnection'; import type { GmcpHandler } from '$lib/gmcp/GmcpHandler'; import { connectionStatus } from '$lib/stores/mudStore'; // Store for active MUD connections (persistent across tab switches) export const activeConnections = writable<{ [key: string]: MudConnection }>({}); /** * ConnectionManager - Singleton service to manage MUD connections * This ensures connections stay alive even when components are unmounted during tab switches */ export class ConnectionManager { private static instance: ConnectionManager; // Private constructor for singleton pattern private constructor() { console.log('ConnectionManager initialized'); } /** * Get the singleton instance of ConnectionManager */ public static getInstance(): ConnectionManager { if (!ConnectionManager.instance) { ConnectionManager.instance = new ConnectionManager(); } return ConnectionManager.instance; } /** * Get an existing connection without creating a new one */ public getExistingConnection(profileId: string): MudConnection | null { const connections = get(activeConnections); return connections[profileId] || null; } /** * Create a new connection or return an existing one */ public getConnection(profileId: string, options: { host: string; port: number; useSSL?: boolean; gmcpHandler?: GmcpHandler; }): MudConnection { // Get current connections const connections = get(activeConnections); // Check if a connection already exists for this profile if (connections[profileId]) { console.log(`Returning existing connection for profile ${profileId}`); return connections[profileId]; } // Create a new connection console.log(`Creating new connection for profile ${profileId}`); const connection = new MudConnection({ host: options.host, port: options.port, useSSL: options.useSSL, gmcpHandler: options.gmcpHandler }); // Set up event handlers this.setupConnectionEvents(connection, profileId); // Store the connection activeConnections.update(connections => ({ ...connections, [profileId]: connection })); // Return the connection return connection; } /** * Connect to a MUD server */ public connect(profileId: string, options: { host: string; port: number; useSSL?: boolean; gmcpHandler?: GmcpHandler; }): void { const connection = this.getConnection(profileId, options); // Update connection status connectionStatus.update(statuses => ({ ...statuses, [profileId]: 'connecting' })); // Connect connection.connect(); } /** * Disconnect from a MUD server */ public disconnect(profileId: string): void { const connections = get(activeConnections); if (connections[profileId]) { connections[profileId].disconnect(); // Update connection status connectionStatus.update(statuses => ({ ...statuses, [profileId]: 'disconnected' })); } } /** * Send text to a MUD server */ public send(profileId: string, text: string): void { const connections = get(activeConnections); if (connections[profileId]) { connections[profileId].send(text); } } /** * Close a connection and remove it */ public closeConnection(profileId: string): void { const connections = get(activeConnections); if (connections[profileId]) { // Disconnect first connections[profileId].disconnect(); // Then remove from store activeConnections.update(connections => { const newConnections = { ...connections }; delete newConnections[profileId]; return newConnections; }); // Update connection status connectionStatus.update(statuses => { const newStatuses = { ...statuses }; delete newStatuses[profileId]; return newStatuses; }); } } /** * Set up event handlers for a connection */ private setupConnectionEvents(connection: MudConnection, profileId: string): void { // Handle connection established connection.on('connected', () => { console.log(`ConnectionManager: Connection established for profile ${profileId}`); // Update connection status connectionStatus.update(statuses => ({ ...statuses, [profileId]: 'connected' })); }); // Handle connection closed connection.on('disconnected', () => { console.log(`ConnectionManager: Connection closed for profile ${profileId}`); // Update connection status connectionStatus.update(statuses => ({ ...statuses, [profileId]: 'disconnected' })); }); // Handle connection error connection.on('error', (error) => { console.error(`ConnectionManager: Connection error for profile ${profileId}:`, error); // Update connection status connectionStatus.update(statuses => ({ ...statuses, [profileId]: 'error' })); }); } }