(function () { const root = document.getElementById("regia-app"); if (!root) return; const cfg = { token: root.dataset.token, statusUrl: root.dataset.statusUrl, scoreUrl: root.dataset.scoreUrl, pauseUrl: root.dataset.pauseUrl, stopUrl: root.dataset.stopUrl, cableUrl: root.dataset.cableUrl, hlsUrl: root.dataset.hlsUrl, homeName: root.dataset.homeName, awayName: root.dataset.awayName, shareUrl: root.dataset.shareUrl, shareTitle: root.dataset.shareTitle, streamClosed: root.dataset.streamClosed === "true" }; const els = { badge: document.getElementById("regia-badge"), setsLine: document.getElementById("sets-line"), scoreLine: document.getElementById("score-line"), partialsLine: document.getElementById("partials-line"), homePoints: document.getElementById("home-points"), toast: document.getElementById("regia-toast"), modal: document.getElementById("regia-modal"), modalTitle: document.getElementById("modal-title"), modalBody: document.getElementById("modal-body"), modalConfirm: document.getElementById("modal-confirm"), modalCancel: document.getElementById("modal-cancel"), preview: document.getElementById("regia-preview"), previewPlaceholder: document.getElementById("regia-preview-placeholder") }; let pendingAction = null; let hls = null; function toast(msg) { els.toast.textContent = msg; els.toast.classList.add("visible"); setTimeout(() => els.toast.classList.remove("visible"), 2800); } function formatPartials(partials) { if (!partials || !partials.length) return ""; return partials .map((p) => `Set ${p.set || p["set"]} ${p.home || p["home"]}-${p.away || p["away"]}`) .join(" · "); } function applyScorePayload(data) { const s = data.score; if (!s) return; const homePts = s.home_points ?? s.homePoints; const awayPts = s.away_points ?? s.awayPoints; const homeSets = s.home_sets ?? s.homeSets; const awaySets = s.away_sets ?? s.awaySets; const currentSet = s.current_set ?? s.currentSet; const awayEl = document.getElementById("away-points"); els.homePoints.textContent = homePts; if (awayEl) awayEl.textContent = awayPts; els.setsLine.textContent = `Set ${currentSet} · Set vinti ${homeSets}-${awaySets}`; els.scoreLine.textContent = `${cfg.homeName} ${homePts} - ${awayPts} ${cfg.awayName}`; const partialsText = formatPartials(s.set_partials || s.setPartials); if (partialsText) { els.partialsLine.textContent = `Parziali: ${partialsText}`; els.partialsLine.hidden = false; } } function setBadge(data) { if (data.stream_closed) { els.badge.textContent = "Terminata"; els.badge.className = "regia-badge regia-badge--ended"; return; } if (data.on_air) { els.badge.textContent = "In onda"; els.badge.className = "regia-badge regia-badge--live"; } else { els.badge.textContent = "In attesa"; els.badge.className = "regia-badge regia-badge--wait"; } } async function postScore(action) { const res = await fetch(cfg.scoreUrl, { method: "PATCH", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify({ cmd: action }) }); if (!res.ok) throw new Error("Errore aggiornamento punteggio"); return res.json(); } async function handleAction(action) { try { const data = await postScore(action); applyScorePayload(data); setBadge(data); if (data.set_won && action !== "close_set") { const winner = data.winner === "home" ? cfg.homeName : cfg.awayName; openModal("Set vinto", `${winner} ha vinto il set. Chiudere il set?`, () => postScore("close_set")); } else if (data.match_won) { const winner = data.winner === "home" ? cfg.homeName : cfg.awayName; openModal("Partita vinta", `${winner} ha vinto la partita. Chiudere la diretta?`, () => stopStream()); } } catch (e) { toast(e.message || "Errore"); } } function openModal(title, body, onConfirm) { els.modalTitle.textContent = title; els.modalBody.textContent = body; els.modal.classList.add("open"); pendingAction = onConfirm; } function closeModal() { els.modal.classList.remove("open"); pendingAction = null; } els.modalConfirm.addEventListener("click", async () => { const fn = pendingAction; closeModal(); if (fn) { try { const data = await fn(); if (data) { applyScorePayload(data); setBadge(data); } } catch (e) { toast(e.message || "Errore"); } } }); els.modalCancel.addEventListener("click", closeModal); root.querySelectorAll("[data-action]").forEach((btn) => { btn.addEventListener("click", () => { const action = btn.dataset.action; if (action === "close_set") { openModal("Chiudi set", "Confermi la chiusura del set corrente?", () => postScore("close_set")); } else { handleAction(action); } }); }); async function pollStatus() { try { const res = await fetch(cfg.statusUrl, { headers: { Accept: "application/json" } }); if (!res.ok) return; const data = await res.json(); applyScorePayload(data); setBadge(data); if (data.stream_closed) { cfg.streamClosed = true; stopPreview(); } } catch (_) {} } function initPreview() { if (cfg.streamClosed || !els.preview || !cfg.hlsUrl) return; if (els.preview.canPlayType("application/vnd.apple.mpegurl")) { els.preview.src = cfg.hlsUrl; } else if (window.Hls && Hls.isSupported()) { hls = new Hls({ maxBufferLength: 8 }); hls.loadSource(cfg.hlsUrl); hls.attachMedia(els.preview); } els.preview.addEventListener("playing", () => { if (els.previewPlaceholder) els.previewPlaceholder.hidden = true; }); } function stopPreview() { if (hls) { hls.destroy(); hls = null; } if (els.preview) els.preview.remove(); if (els.previewPlaceholder) { els.previewPlaceholder.hidden = false; els.previewPlaceholder.textContent = "Diretta terminata"; } } async function pauseStream() { await fetch(cfg.pauseUrl, { method: "POST", headers: { Accept: "application/json" } }); toast("Trasmissione in pausa"); } async function stopStream() { const ok = confirm("Chiudere definitivamente la diretta?"); if (!ok) return null; const res = await fetch(cfg.stopUrl, { method: "POST", headers: { Accept: "application/json" } }); if (!res.ok) throw new Error("Errore chiusura"); const data = await res.json(); cfg.streamClosed = true; stopPreview(); toast("Diretta chiusa"); return data; } document.getElementById("btn-pause")?.addEventListener("click", () => pauseStream().catch((e) => toast(e.message))); document.getElementById("btn-stop")?.addEventListener("click", () => stopStream().catch((e) => toast(e.message))); async function shareLink() { const payload = { title: cfg.shareTitle, text: "Apri questo link per gestire il punteggio della diretta:", url: cfg.shareUrl }; if (navigator.share) { try { await navigator.share(payload); return; } catch (err) { if (err.name === "AbortError") return; } } await copyLink(); } async function copyLink() { try { await navigator.clipboard.writeText(cfg.shareUrl); toast("Link copiato"); } catch (_) { prompt("Copia il link:", cfg.shareUrl); } } document.getElementById("btn-share")?.addEventListener("click", () => shareLink()); document.getElementById("btn-copy")?.addEventListener("click", () => copyLink()); initPreview(); setInterval(pollStatus, 4000); pollStatus(); })();