// Breathing circle for the Meditation page.
//
// Three patterns:
//   box      — 4 in · 4 hold · 4 out · 4 hold  (square breathing)
//   coherent — 5 in · 5 out  (HRV-maximizing, no holds)
//   relax    — 4 in · 7 hold · 8 out  (Dr. Andrew Weil's pattern; deep calm)
//
// Pauses automatically when the meditation view isn't active so the
// animation isn't burning CPU in the background.

(function () {
  const PATTERNS = {
    box: [
      { name: "inhale", duration: 4 },
      { name: "hold",   duration: 4 },
      { name: "exhale", duration: 4 },
      { name: "hold",   duration: 4 },
    ],
    coherent: [
      { name: "inhale", duration: 5 },
      { name: "exhale", duration: 5 },
    ],
    relax: [
      { name: "inhale", duration: 4 },
      { name: "hold",   duration: 7 },
      { name: "exhale", duration: 8 },
    ],
  };

  // Range the circle scales between on exhale↔inhale. Subtle min keeps the
  // circle visible at full exhale; max under 1 keeps it inside the chrome.
  const MIN_SCALE = 0.42;
  const MAX_SCALE = 1.00;

  let pattern = loadPattern();
  let phaseIdx = 0;
  let elapsed = 0;          // ms into current phase
  let isPlaying = false;
  let lastTs = null;
  let rafId = null;

  // DOM
  const root      = document.getElementById("breath");
  if (!root) return;
  const circle    = root.querySelector(".breath-circle");
  const phaseEl   = root.querySelector(".breath-phase");
  const countEl   = root.querySelector(".breath-count");
  const playBtn   = root.querySelector(".breath-play");
  const patternEls= root.querySelectorAll(".breath-pattern[data-pattern]");

  function t(key, fallback) {
    return (window.i18n && window.i18n.t) ? window.i18n.t(key, fallback) : fallback;
  }

  function loadPattern() {
    try {
      const saved = localStorage.getItem("wuys-breath-pattern");
      if (saved && PATTERNS[saved]) return saved;
    } catch (_) { /* ignore */ }
    return "box";
  }
  function savePattern(p) {
    try { localStorage.setItem("wuys-breath-pattern", p); } catch (_) { /* ignore */ }
  }

  function phaseLabel(name) {
    if (name === "inhale") return t("page.meditation.breath_inhale", "Breathe in");
    if (name === "exhale") return t("page.meditation.breath_exhale", "Breathe out");
    return t("page.meditation.breath_hold", "Hold");
  }

  function currentPhase() {
    return PATTERNS[pattern][phaseIdx];
  }

  function prevPhaseName() {
    const arr = PATTERNS[pattern];
    return arr[(phaseIdx - 1 + arr.length) % arr.length].name;
  }

  function applyScale() {
    const ph = currentPhase();
    const phaseMs = ph.duration * 1000;
    const progress = Math.min(1, elapsed / phaseMs);
    let scale;
    if (ph.name === "inhale") {
      scale = MIN_SCALE + (MAX_SCALE - MIN_SCALE) * progress;
    } else if (ph.name === "exhale") {
      scale = MAX_SCALE - (MAX_SCALE - MIN_SCALE) * progress;
    } else {
      // Hold — stay at whatever the previous phase ended at.
      const prev = prevPhaseName();
      scale = (prev === "inhale") ? MAX_SCALE : MIN_SCALE;
    }
    circle.style.transform = "translate(-50%, -50%) scale(" + scale.toFixed(3) + ")";
    circle.style.opacity = (0.55 + (scale - MIN_SCALE) * 0.45).toFixed(3);
  }

  function updateLabels() {
    const ph = currentPhase();
    phaseEl.textContent = phaseLabel(ph.name);
    const remaining = Math.max(0, ph.duration - elapsed / 1000);
    countEl.textContent = Math.ceil(remaining) || ph.duration;
  }

  function tick(ts) {
    if (!isPlaying) return;
    if (lastTs == null) lastTs = ts;
    const dt = ts - lastTs;
    lastTs = ts;
    elapsed += dt;
    const phaseMs = currentPhase().duration * 1000;
    if (elapsed >= phaseMs) {
      elapsed -= phaseMs;
      phaseIdx = (phaseIdx + 1) % PATTERNS[pattern].length;
    }
    applyScale();
    updateLabels();
    rafId = requestAnimationFrame(tick);
  }

  function start() {
    if (isPlaying) return;
    isPlaying = true;
    lastTs = null;
    playBtn.textContent = t("page.meditation.breath_pause", "Pause");
    playBtn.setAttribute("aria-pressed", "true");
    rafId = requestAnimationFrame(tick);
  }

  function pause() {
    if (!isPlaying) return;
    isPlaying = false;
    if (rafId) cancelAnimationFrame(rafId);
    rafId = null;
    playBtn.textContent = t("page.meditation.breath_begin", "Begin");
    playBtn.setAttribute("aria-pressed", "false");
  }

  function reset(toPattern) {
    pause();
    if (toPattern && PATTERNS[toPattern]) {
      pattern = toPattern;
      savePattern(pattern);
    }
    phaseIdx = 0;
    elapsed = 0;
    applyScale();
    updateLabels();
    patternEls.forEach((el) => {
      el.classList.toggle("active", el.dataset.pattern === pattern);
    });
  }

  // ----- Wiring ------------------------------------------------------------
  playBtn.addEventListener("click", () => {
    if (isPlaying) pause(); else start();
  });
  patternEls.forEach((el) => {
    el.addEventListener("click", () => reset(el.dataset.pattern));
  });

  // Re-render labels when the user switches language so they update live.
  window.addEventListener("langchange", () => {
    playBtn.textContent = isPlaying
      ? t("page.meditation.breath_pause", "Pause")
      : t("page.meditation.breath_begin", "Begin");
    updateLabels();
  });

  // Pause whenever the meditation view leaves the screen — saves CPU and
  // avoids the circle racing in the background after the user navigates away.
  const meditationView = document.querySelector('.view[data-view="meditation"]');
  if (meditationView && "MutationObserver" in window) {
    new MutationObserver(() => {
      if (!meditationView.classList.contains("active") && isPlaying) pause();
    }).observe(meditationView, { attributes: true, attributeFilter: ["class"] });
  }
  // Also pause when the tab is hidden.
  document.addEventListener("visibilitychange", () => {
    if (document.hidden && isPlaying) pause();
  });

  reset();
})();
