import { ChainEvent, EventFilter } from '../types';

type EventCallback = (event: ChainEvent) => void;

export class EventModule {
  private ws: WebSocket | null = null;
  private listeners = new Map<string, Set<EventCallback>>();

  constructor(private wsUrl: string) {}

  on(eventName: string, callback: EventCallback): void {
    if (!this.listeners.has(eventName)) {
      this.listeners.set(eventName, new Set());
    }
    this.listeners.get(eventName)!.add(callback);
    this.ensureConnected();
  }

  off(eventName: string, callback: EventCallback): void {
    this.listeners.get(eventName)?.delete(callback);
  }

  subscribe(filter: EventFilter): void {
    this.ensureConnected();
    this.ws?.send(JSON.stringify({ type: 'subscribe', filter }));
  }

  unsubscribe(filter: EventFilter): void {
    this.ws?.send(JSON.stringify({ type: 'unsubscribe', filter }));
  }

  private ensureConnected(): void {
    if (this.ws) return;

    this.ws = new WebSocket(this.wsUrl);

    this.ws.onmessage = (msg) => {
      const event: ChainEvent = JSON.parse(msg.data.toString());
      this.listeners.get(event.type)?.forEach((cb) => cb(event));
      this.listeners.get('*')?.forEach((cb) => cb(event));
    };

    this.ws.onclose = () => {
      this.ws = null;
      // 自动重连
      setTimeout(() => this.ensureConnected(), 3000);
    };
  }
}
