// ═══════════════════════════════════════════════════════
//  CVC Dashboard — WebSocket Client
//  (Compiled from ts/ws.ts — edit TypeScript source)
// ═══════════════════════════════════════════════════════
"use strict";

class DashboardWS {
  constructor() {
    /** @type {WebSocket|null} */
    this.ws = null;
    const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
    /** @type {string} */
    this.url = `${proto}//${location.host}/ws/dashboard`;
    /** @type {Function[]} */
    this.listeners = [];
    /** @type {ReturnType<typeof setTimeout>|null} */
    this.reconnectTimer = null;
    /** @type {number} */
    this.reconnectDelay = 2000;
    /** @type {number} */
    this.maxReconnectDelay = 30000;
    /** @type {boolean} */
    this.alive = true;
  }

  connect() {
    if (this.ws?.readyState === WebSocket.OPEN) return;
    try {
      this.ws = new WebSocket(this.url);
    } catch {
      this._scheduleReconnect();
      return;
    }

    this.ws.onopen = () => {
      this.reconnectDelay = 2000;
      this._updateIndicator(true);
    };

    this.ws.onmessage = (ev) => {
      try {
        const msg = JSON.parse(ev.data);
        for (const cb of this.listeners) cb(msg);
      } catch { /* ignore bad frames */ }
    };

    this.ws.onclose = () => {
      this._updateIndicator(false);
      if (this.alive) this._scheduleReconnect();
    };

    this.ws.onerror = () => {
      this.ws?.close();
    };
  }

  /** @param {Function} cb */
  on(cb) { this.listeners.push(cb); }

  /** @param {Function} cb */
  off(cb) { this.listeners = this.listeners.filter(l => l !== cb); }

  /** @param {*} msg */
  send(msg) {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(msg));
    }
  }

  disconnect() {
    this.alive = false;
    if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
    this.ws?.close();
  }

  _scheduleReconnect() {
    if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
    this.reconnectTimer = setTimeout(() => this.connect(), this.reconnectDelay);
    this.reconnectDelay = Math.min(this.reconnectDelay * 1.5, this.maxReconnectDelay);
  }

  _updateIndicator(connected) {
    const dot = document.querySelector('#ws-status .ws-dot');
    const label = document.querySelector('#ws-status .ws-label');
    if (dot) {
      dot.classList.toggle('connected', connected);
      dot.classList.toggle('disconnected', !connected);
    }
    if (label) label.textContent = connected ? 'Connected' : 'Disconnected';
  }
}
