/**
 * Client leger de connexion aux evenements TikTok Live diffuses par le serveur.
 * Usage: TikTokEvents.on('like', (data) => { ... })
 */
const TikTokEvents = (() => {
  const listeners = new Map();
  const sendQueue = [];
  let socket = null;
  let reconnectDelay = 1000;

  function emit(type, data) {
    const cbs = listeners.get(type);
    if (cbs) cbs.forEach((cb) => cb(data));
  }

  function connect() {
    const protocol = location.protocol === 'https:' ? 'wss' : 'ws';
    socket = new WebSocket(`${protocol}://${location.host}/ws`);

    socket.addEventListener('open', () => {
      reconnectDelay = 1000;
      emit('_status', { connected: true });
      while (sendQueue.length) socket.send(sendQueue.shift());
    });

    function handlePayload(text) {
      try {
        const data = JSON.parse(text);
        emit(data.type, data);
        emit('_any', data);
      } catch (e) {
        console.warn('[TikTokEvents] message illisible ignore :', text, e);
      }
    }

    socket.addEventListener('message', (event) => {
      // Normalement du texte, mais on accepte aussi une trame binaire (Blob)
      // plutot que de perdre l'evenement sans rien dire.
      if (typeof event.data === 'string') handlePayload(event.data);
      else if (event.data instanceof Blob) event.data.text().then(handlePayload);
    });

    socket.addEventListener('close', () => {
      emit('_status', { connected: false });
      setTimeout(connect, reconnectDelay);
      reconnectDelay = Math.min(reconnectDelay * 1.5, 10000);
    });
  }

  connect();

  return {
    on(type, callback) {
      if (!listeners.has(type)) listeners.set(type, new Set());
      listeners.get(type).add(callback);
      return () => listeners.get(type).delete(callback);
    },
    // Envoie un message au serveur, qui le retransmet a tous les autres clients
    // connectes (jeu <-> overlay), meme dans des navigateurs differents.
    send(data) {
      const payload = JSON.stringify(data);
      if (socket && socket.readyState === 1) socket.send(payload);
      else sendQueue.push(payload);
    }
  };
})();
