// @wuys/map · core/events.js
// Tiny event bus. One per map instance. Handlers receive (payload).
// Event names are conventionally `domain:action` — e.g. "country:click", "nav:change".

export function createEventBus() {
  const handlers = new Map(); // event → Set<handler>

  function on(event, handler) {
    if (!handlers.has(event)) handlers.set(event, new Set());
    handlers.get(event).add(handler);
    // Return an unsubscriber for ergonomics.
    return () => off(event, handler);
  }

  function off(event, handler) {
    const set = handlers.get(event);
    if (set) set.delete(handler);
  }

  function once(event, handler) {
    const wrapped = (payload) => {
      off(event, wrapped);
      handler(payload);
    };
    return on(event, wrapped);
  }

  function emit(event, payload) {
    const set = handlers.get(event);
    if (!set || set.size === 0) return;
    // Iterate a snapshot so handlers can remove themselves without breaking the loop.
    for (const handler of [...set]) {
      try {
        handler(payload);
      } catch (err) {
        // One bad handler shouldn't break the others — log and continue.
        console.error("[wuys/map] event handler threw for", event, err);
      }
    }
  }

  function clear() {
    handlers.clear();
  }

  return { on, off, once, emit, clear };
}
