/* ============================================================
   Radio Ultra – app.js
   ============================================================ */
(() => {
  'use strict';

  const audio      = document.getElementById('audioPlayer');
  const btnPlay    = document.getElementById('btnPlay');
  const btnStop    = document.getElementById('btnStop');
  const playerName = document.getElementById('playerName');
  const playerMeta = document.getElementById('playerMeta');
  const playerLogo = document.getElementById('playerLogo');
  const playerFb   = document.getElementById('playerLogoFallback');
  const stickyPl   = document.getElementById('stickyPlayer');
  const volSlider  = document.getElementById('volume');
  const cards      = [...document.querySelectorAll('.station-card')];
  const searchEl   = document.getElementById('search');
  const noResults  = document.getElementById('noResults');
  const genreFilter= document.getElementById('genreFilter');
  const btnWake    = document.getElementById('btnWake');
  const btnCast    = document.getElementById('btnCast');
  if (btnCast) btnCast.style.display = 'inline-flex';

  let currentId    = null;
  let metaTimer    = null;
  let filterGenre  = '';
  let filterSearch = '';
  let isPlaying    = false;
  let wakeLock     = null;
  let wakeWanted   = false;
  let currentStation = null;
  let isCasting      = false;


  // ── Radio Engfeldt Cast integration ─────────────────────────
  window.__onGCastApiAvailable = function(isAvailable) {
    if (isAvailable) initCast();
  };

  function castReady() {
    return !!(window.cast && window.chrome && chrome.cast && cast.framework);
  }

  function getCastSession() {
    if (!castReady()) return null;
    return cast.framework.CastContext.getInstance().getCurrentSession();
  }

  function getCastContentType(url) {
    const cleanUrl = (url || '').split('?')[0].toLowerCase();

    if (cleanUrl.endsWith('.m3u8')) return 'application/vnd.apple.mpegurl';
    if (cleanUrl.endsWith('.aac'))  return 'audio/aac';
    if (cleanUrl.endsWith('.ogg'))  return 'audio/ogg';
    if (cleanUrl.endsWith('.opus')) return 'audio/ogg';
    if (cleanUrl.endsWith('.wav'))  return 'audio/wav';

    return 'audio/mpeg';
  }

  function initCast() {
    if (!castReady()) return;

    try {
      const context = cast.framework.CastContext.getInstance();

      context.setOptions({
        receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,
        autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
      });

      context.addEventListener(
        cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
        event => {
          if (
            event.sessionState === cast.framework.SessionState.SESSION_STARTED ||
            event.sessionState === cast.framework.SessionState.SESSION_RESUMED
          ) {
            castCurrentStation();
          }

          if (event.sessionState === cast.framework.SessionState.SESSION_ENDED) {
            isCasting = false;
          }
        }
      );

      if (btnCast) btnCast.style.display = 'inline-flex';
    } catch (err) {
      console.warn('Google Cast kunde inte initieras:', err);
    }
  }

  function castCurrentStation() {
    const session = getCastSession();

    if (!session || !currentStation || !currentStation.url) return;

    const absoluteLogo = currentStation.logo
      ? new URL(currentStation.logo, window.location.href).href
      : '';

    const contentType = getCastContentType(currentStation.url);
    const mediaInfo = new chrome.cast.media.MediaInfo(currentStation.url, contentType);

    mediaInfo.streamType = chrome.cast.media.StreamType.LIVE;
    mediaInfo.contentType = contentType;

    const metadata = new chrome.cast.media.MusicTrackMediaMetadata();
    metadata.title = currentStation.name || 'Radio Engfeldt';
    metadata.artist = currentStation.meta || 'Live radio';

    if (absoluteLogo) {
      metadata.images = [new chrome.cast.Image(absoluteLogo)];
    }

    mediaInfo.metadata = metadata;

    const request = new chrome.cast.media.LoadRequest(mediaInfo);
    request.autoplay = true;

    session.loadMedia(request).then(() => {
      isCasting = true;

      audio.pause();

      isPlaying = true;
      updatePlayBtn();

      playerMeta.textContent = currentStation.meta || 'Castar till Google Home / Chromecast…';
    }).catch(err => {
      console.warn('Kunde inte starta Cast-uppspelning:', err);
      playerMeta.textContent = 'Kunde inte casta denna kanal.';
    });
  }

  if (castReady()) initCast();

  if (btnCast) {
    btnCast.addEventListener('click', () => {
      alert('Cast-knappen fungerar. Kontrollerar Google Cast...');

      if (!currentStation || !currentStation.url) {
        alert('Starta en radiokanal först. Tryck sedan på Casta igen.');
        return;
      }

      if (!window.chrome) {
        alert('window.chrome saknas. Testa i Google Chrome, inte Safari/Firefox.');
        return;
      }

      if (!window.cast || !chrome.cast || !window.cast.framework) {
        alert('Google Cast SDK är inte aktivt. Trolig orsak: sidan körs utan HTTPS eller Cast SDK blockeras.');
        console.warn('Cast debug:', {
          protocol: window.location.protocol,
          host: window.location.host,
          hasChrome: !!window.chrome,
          hasCast: !!window.cast,
          hasChromeCast: !!(window.chrome && chrome.cast),
          hasFramework: !!(window.cast && cast.framework)
        });
        return;
      }

      try {
        initCast();

        const context = cast.framework.CastContext.getInstance();

        alert('Google Cast SDK är aktivt. Nu öppnas Cast-väljaren.');

        context.requestSession()
          .then(() => {
            alert('Cast-session startad. Skickar radiokanalen till enheten.');
            castCurrentStation();
          })
          .catch(err => {
            alert('Cast-väljaren avbröts eller misslyckades. Se Console/F12 för detaljer.');
            console.warn('Cast requestSession error:', err);
          });

      } catch (err) {
        alert('Fel vid Cast-start: ' + (err && err.message ? err.message : err));
        console.error('Cast start error:', err);
      }
    });
  }

  let castInitAttempts = 0;
  function retryCastInit() {
    castInitAttempts++;
    if (castReady()) {
      initCast();
      return;
    }
    if (castInitAttempts < 20) {
      setTimeout(retryCastInit, 500);
    }
  }
  retryCastInit();

  // ── Wake Lock (håller skärmen vaken under uppspelning) ───────
  async function requestWakeLock() {
    if (!('wakeLock' in navigator)) return;
    try {
      wakeLock = await navigator.wakeLock.request('screen');
      wakeLock.addEventListener('release', () => updateWakeBtn());
      updateWakeBtn();
    } catch (err) {
      console.warn('Wake Lock kunde inte aktiveras:', err);
    }
  }

  function releaseWakeLock() {
    if (wakeLock) { wakeLock.release(); wakeLock = null; }
    updateWakeBtn();
  }

  function updateWakeBtn() {
    if (!btnWake) return;
    const active = !!wakeLock;
    btnWake.classList.toggle('active', active);
    btnWake.title = active ? 'Skärmen hålls vaken (klicka för att stänga av)' : 'Håll skärmen vaken';
    const moonIcon = btnWake.querySelector('.icon-moon');
    const sunIcon  = btnWake.querySelector('.icon-sun');
    if (moonIcon && sunIcon) {
      moonIcon.style.display = active ? 'none' : '';
      sunIcon.style.display  = active ? '' : 'none';
    }
  }

  if (btnWake) {
    if (!('wakeLock' in navigator)) {
      btnWake.style.display = 'none';
    } else {
      btnWake.addEventListener('click', () => {
        wakeWanted = !wakeWanted;
        if (wakeWanted) requestWakeLock(); else releaseWakeLock();
      });
    }
  }

  // Återaktivera wake lock om fliken döljs och visas igen (t.ex. surfplattan väcks)
  document.addEventListener('visibilitychange', () => {
    if (wakeWanted && document.visibilityState === 'visible' && !wakeLock) {
      requestWakeLock();
    }
  });

  // ── Volume ──────────────────────────────────────────────────
  audio.volume = parseFloat(volSlider.value);
  volSlider.addEventListener('input', () => { audio.volume = parseFloat(volSlider.value); });

  // ── Play card ───────────────────────────────────────────────
  function playCard(card) {
    const id   = card.dataset.id;
    const url  = card.dataset.url;
    const name = card.dataset.name;
    const logo = card.dataset.logo;
    const init = card.dataset.initial;

    if (!url) return;

    currentStation = { id, url, name, logo, init, meta: '' };

    // Avbryt ev. pågående återanslutningsförsök för föregående kanal
    clearTimeout(reconnectTimer); reconnectTimer = null;
    clearTimeout(stallTimer);
    reconnectAttempts = 0;

    // Highlight
    cards.forEach(c => c.classList.remove('playing'));
    card.classList.add('playing');

    // Audio
    audio.pause();
    audio.src = url;
    audio.load();
    audio.play().catch(() => {});

    if (getCastSession()) {
      castCurrentStation();
    }

    currentId = id;
    isPlaying = true;
    updatePlayBtn();

    // Player strip
    playerName.textContent = name;
    playerMeta.textContent = '';
    stickyPl.style.display = 'flex';

    if (logo) {
      playerLogo.src = logo;
      playerLogo.style.display = 'block';
      playerFb.style.display = 'none';
    } else {
      playerLogo.style.display = 'none';
      playerFb.textContent = init;
      playerFb.style.display = 'flex';
    }

    // Log play (fire & forget)
    fetch('api/live.php', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({station_id: id})
    }).catch(() => {});

    // Aktivera wake lock automatiskt när uppspelning startar (om inte redan satt)
    if (!wakeWanted) { wakeWanted = true; requestWakeLock(); }

    // Start metadata polling
    clearInterval(metaTimer);
    fetchMeta(id);
    metaTimer = setInterval(() => fetchMeta(id), 30000);
  }

  function updatePlayBtn() {
    btnPlay.textContent = isPlaying ? '⏸' : '▶';
  }

  // ── Metadata fetch ──────────────────────────────────────────
  function fetchMeta(stationId) {
    fetch('api/station.php?id=' + stationId)
      .then(r => r.json())
      .then(data => {
        const text = [data.artist, data.title].filter(Boolean).join(' – ');
        playerMeta.textContent = text;
        if (currentStation && String(currentStation.id) === String(stationId)) {
          currentStation.meta = text;
        }
        const el = document.getElementById('meta-' + stationId);
        if (el) el.textContent = text;
      })
      .catch(() => {});
  }

  // ── Controls ────────────────────────────────────────────────
  btnPlay.addEventListener('click', () => {
    if (!audio.src) return;
    if (isPlaying) { audio.pause(); isPlaying = false; }
    else           { audio.play().catch(() => {}); isPlaying = true; }
    updatePlayBtn();
  });

  btnStop.addEventListener('click', () => {
    currentId = null; // sätt först, så ev. pågående reconnect avbryts
    clearTimeout(reconnectTimer); reconnectTimer = null;
    clearTimeout(stallTimer);
    reconnectAttempts = 0;
    audio.pause();
    audio.src = '';
    isCasting = false;
    isPlaying = false;
    updatePlayBtn();
    stickyPl.style.display = 'none';
    cards.forEach(c => c.classList.remove('playing'));
    clearInterval(metaTimer);
    wakeWanted = false;
    releaseWakeLock();
  });

  audio.addEventListener('play',  () => { isPlaying = true;  updatePlayBtn(); });
  audio.addEventListener('pause', () => { isPlaying = false; updatePlayBtn(); });

  // ── Auto-reconnect vid buffring/avbrott ──────────────────────
  let reconnectAttempts = 0;
  let reconnectTimer    = null;
  let stallTimer        = null;
  const MAX_RECONNECT_DELAY = 15000; // 15s tak mellan försök

  function scheduleReconnect(reason) {
    if (!currentId || reconnectTimer) return; // redan på väg, eller inget aktivt val

    const card = cards.find(c => c.dataset.id === currentId);
    if (!card) return;

    const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), MAX_RECONNECT_DELAY);
    reconnectAttempts++;

    console.warn(`Radio Ultra: återansluter om ${delay}ms (${reason}, försök ${reconnectAttempts})`);
    playerMeta.textContent = 'Återansluter…';

    reconnectTimer = setTimeout(() => {
      reconnectTimer = null;
      if (!currentId) return; // stoppad under tiden
      const wasVolume = audio.volume;
      audio.src = '';
      audio.src = card.dataset.url;
      audio.volume = wasVolume;
      audio.load();
      audio.play().catch(() => {});
    }, delay);
  }

  audio.addEventListener('playing', () => {
    // Lyckad uppspelning – återställ backoff-räknaren
    reconnectAttempts = 0;
    if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; }
  });

  audio.addEventListener('error', () => {
    if (currentId) scheduleReconnect('error');
  });

  // 'stalled' = bytes slutade komma in (vanligt vid nätverksglapp)
  audio.addEventListener('stalled', () => {
    if (!currentId) return;
    clearTimeout(stallTimer);
    stallTimer = setTimeout(() => {
      if (audio.paused || audio.readyState < 3) scheduleReconnect('stalled');
    }, 4000);
  });

  // 'waiting' = bufferunderskott, normalt kortvarigt men kan fastna
  audio.addEventListener('waiting', () => {
    if (!currentId) return;
    clearTimeout(stallTimer);
    stallTimer = setTimeout(() => {
      if (audio.readyState < 3) scheduleReconnect('waiting too long');
    }, 8000);
  });

  audio.addEventListener('canplay', () => clearTimeout(stallTimer));

  // ── Card click ──────────────────────────────────────────────
  cards.forEach(card => {
    card.addEventListener('click', e => {
      if (e.target.closest('.btn-card-play') || e.currentTarget === card) {
        if (card.dataset.id === currentId && isPlaying) {
          audio.pause(); isPlaying = false; updatePlayBtn();
          card.classList.remove('playing');
          return;
        }
        playCard(card);
      }
    });
  });

  // ── Search & Filter ─────────────────────────────────────────
  function applyFilter() {
    let visible = 0;
    cards.forEach(card => {
      const matchGenre  = !filterGenre  || card.dataset.genre === filterGenre;
      const matchSearch = !filterSearch || card.dataset.name.toLowerCase().includes(filterSearch);
      const show = matchGenre && matchSearch;
      card.style.display = show ? '' : 'none';
      if (show) visible++;
    });
    noResults.style.display = visible === 0 ? 'block' : 'none';
  }

  searchEl.addEventListener('input', () => {
    filterSearch = searchEl.value.toLowerCase().trim();
    applyFilter();
  });

  genreFilter.addEventListener('click', e => {
    const chip = e.target.closest('.chip');
    if (!chip) return;
    document.querySelectorAll('.chip').forEach(c => c.classList.remove('active'));
    chip.classList.add('active');
    filterGenre = chip.dataset.genre;
    applyFilter();
  });

  // ── Keyboard ────────────────────────────────────────────────
  document.addEventListener('keydown', e => {
    if (e.target.tagName === 'INPUT') return;
    if (e.code === 'Space')     { e.preventDefault(); btnPlay.click(); }
    if (e.code === 'KeyS')      { btnStop.click(); }
  });

})();
