// ponytail: tiny event bus so tools can push data to each other without
// a shared store. Survives component unmounts via a module-level emitter.
// Use sparingly: only for cross-tool flows (Encounter → Initiative, Item →
// Lore, etc.). The History view stays the single source of truth for
// rehydrating past results.

type Handler<T> = (payload: T) => void;

interface CombatantInput {
  name: string;
  initiative?: number;
  hp: number;
}

class EventBus {
  private map = new Map<string, Set<Handler<unknown>>>();

  on<T>(event: string, handler: Handler<T>): () => void {
    const set = this.map.get(event) ?? new Set();
    set.add(handler as Handler<unknown>);
    this.map.set(event, set);
    return () => {
      set.delete(handler as Handler<unknown>);
    };
  }

  emit<T>(event: string, payload: T): void {
    const set = this.map.get(event);
    if (!set) return;
    for (const h of set) {
      try {
        h(payload);
      } catch (e) {
        console.error(`[EventBus] handler for ${event} threw:`, e);
      }
    }
  }
}

export const bus = new EventBus();

// ─── Event names + payload types ────────────────────────────

export const Events = {
  AddCombatants: "add-combatants",
  PlayAmbient: "play-ambient",
} as const;

export type AddCombatantsPayload = {
  combatants: CombatantInput[];
  /** Source label, e.g. "Goblin Ambush (Easy)" — shown in the toast. */
  source: string;
};

export type PlayAmbientPayload = {
  /** Ambient sound id from the Soundboard (rain, wind, fire, …). */
  id: string;
  source: string;
};
