/**
 * event-bus.mjs — Typed event dispatcher with history buffer
 * Extends EventTarget for native event support
 */

const MAX_HISTORY = 200;

const EVENTS = {
  // Agent
  AGENT_STATUS: 'agent:status',

  // Chat
  CHAT_MESSAGE: 'chat:message',
  CHAT_STREAM_CHUNK: 'chat:stream-chunk',
  CHAT_STREAM_END: 'chat:stream-end',
  CHAT_STREAM_ERROR: 'chat:stream-error',

  // Activity
  ACTIVITY_EVENT: 'activity:event',

  // Voice
  VOICE_STATE_CHANGE: 'voice:state-change',
  VOICE_TRANSCRIPT: 'voice:transcript',

  // WebSocket
  WS_CONNECTED: 'ws:connected',
  WS_DISCONNECTED: 'ws:disconnected',
  WS_MESSAGE: 'ws:message',

  // Skills
  SKILL_START: 'skill:start',
  SKILL_COMPLETE: 'skill:complete',

  // UI
  VIEW_CHANGE: 'ui:view-change',
  THEME_CHANGE: 'ui:theme-change',
  NOTIFICATION: 'ui:notification'
};

class EventBus extends EventTarget {
  constructor() {
    super();
    this._history = [];
    this._buffering = false;
    this._buffer = [];
  }

  emit(type, data) {
    const entry = { type, data, timestamp: Date.now() };

    if (this._buffering) {
      this._buffer.push(entry);
      return;
    }

    this._addToHistory(entry);
    this.dispatchEvent(new CustomEvent(type, { detail: data }));
  }

  on(type, callback) {
    const handler = (e) => callback(e.detail);
    this.addEventListener(type, handler);
    return () => this.removeEventListener(type, handler);
  }

  once(type, callback) {
    const handler = (e) => callback(e.detail);
    this.addEventListener(type, handler, { once: true });
  }

  startBuffering() {
    this._buffering = true;
    this._buffer = [];
  }

  flushBuffer() {
    this._buffering = false;
    const buffered = [...this._buffer];
    this._buffer = [];
    for (const entry of buffered) {
      this._addToHistory(entry);
      this.dispatchEvent(new CustomEvent(entry.type, { detail: entry.data }));
    }
  }

  getHistory(type, limit = 50) {
    const items = type
      ? this._history.filter(e => e.type === type)
      : this._history;
    return items.slice(-limit);
  }

  clearHistory() {
    this._history = [];
  }

  _addToHistory(entry) {
    this._history.push(entry);
    if (this._history.length > MAX_HISTORY) {
      this._history = this._history.slice(-MAX_HISTORY);
    }
  }
}

// Singleton
const eventBus = new EventBus();
export default eventBus;
export { EVENTS };
