/* widget: Ballonnenwoord */
/* =========================================================
Balloon word widget — guess before the balloons pop
==========================================================*/
function mountBall(root, initState, opts){
const onProgress = opts && opts.onProgress;
const S = { level:1, yearGroup:null, managedLearningLevel:false, card:0, snd:true, lives:6, guessed:new Set(), over:false, order:[], idx:0, stars:0 };
if(initState){S.level=initState.level||1;S.yearGroup=initState.yearGroup||null;S.managedLearningLevel=!!initState.managedLearningLevel;S.card = initState.card ?? 0; S.snd = initState.snd !== false;}
const assignedRules=languageTaskRules(S.yearGroup,S.level),maxLives=assignedRules?.lives||6;
const play = f=>{ if(S.snd) f(); };
root.innerHTML = `
`;
const el = s => root.querySelector(s);
const srcSel = el(".bl-src"), balloonsEl = el(".bl-balloons"),
wordEl = el(".bl-word"), msgEl = el(".bl-msg"),
nextBtn = el(".bl-next"), kbdEl = el(".bl-kbd"),
scoreEl = el(".bl-score"), sndBtn = el(".lg-snd");
function list(){ S.card = normWordSource(S.card); return languageWordsForYear(wordSourceList(S.card),S.yearGroup,S.level); }
function buildSrc(){ fillWordSourceSel(srcSel, S.card); }
"abcdefghijklmnopqrstuvwxyz".split("").forEach(l=>{
const b = document.createElement("button");
b.textContent = l; b.dataset.l = l;
b.className = VOWELS.includes(l) ? "v" : "c";
b.addEventListener("click", ()=>guess(l, b));
kbdEl.appendChild(b);
});
function word(){ return list()[S.order[S.idx]][0]; }
function drawWord(reveal){
wordEl.textContent = word().split("").map(l=>(reveal || S.guessed.has(l)) ? l : "_").join(" ");
}
function drawBalloons(){
balloonsEl.textContent = "🎈".repeat(S.lives) + "💥".repeat(maxLives-S.lives);
}
function newWord(){
if(!S.order.length || S.idx >= S.order.length){
S.order = shuffle(list().map((_,i)=>i));
S.idx = 0;
}
S.lives = maxLives; S.guessed = new Set(); S.over = false;
msgEl.textContent = ""; msgEl.className = "bl-msg";
nextBtn.classList.remove("show");
kbdEl.querySelectorAll("button").forEach(b=>{ b.disabled = false; b.style.opacity = 1; });
drawWord(false); drawBalloons();
scoreEl.textContent = S.stars ? S.stars+" ★" : "";
}
function guess(l, btn){
if(S.over || btn.disabled) return;
btn.disabled = true; btn.style.opacity = .3;
if(word().includes(l)){
S.guessed.add(l);
play(sndGood);
drawWord(false);
if(word().split("").every(x=>S.guessed.has(x))){
S.over = true; S.stars++;
msgEl.textContent = T("ballWin");
msgEl.classList.add("win");
play(sndWin); confetti(el(".mt-card"));
nextBtn.classList.add("show");
scoreEl.textContent = S.stars+" ★";
if(onProgress) onProgress({ attempts: 1, correct: 1, stars: 1 });
}
}else{
S.lives--;
play(sndBad);
drawBalloons();
if(S.lives <= 0){
S.over = true;
drawWord(true);
msgEl.textContent = `${T("ballLose")} ${word()}`;
msgEl.classList.add("lose");
nextBtn.classList.add("show");
}
}
}
nextBtn.addEventListener("click", ()=>{ S.idx++; newWord(); });
srcSel.addEventListener("change", ()=>{
S.card = srcSel.value;
S.order = []; newWord();
});
sndBtn.addEventListener("click", ()=>{
S.snd = !S.snd;
sndBtn.textContent = S.snd ? "🔔" : "🔕";
sndBtn.classList.toggle("off", !S.snd);
});
function labels(){
sndBtn.textContent = S.snd ? "🔔" : "🔕";
sndBtn.classList.toggle("off", !S.snd);
sndBtn.title = T("sndWidget");
nextBtn.textContent = T("next");
buildSrc();
}
document.addEventListener("langchange", ()=>{ S.card=0; S.order=[]; labels(); newWord(); });
document.addEventListener("wordschange", ()=>{ buildSrc(); S.order=[]; newWord(); });
labels(); newWord();
root.classList.toggle("managed-learning-level",S.managedLearningLevel);
return { getState: ()=>({card:S.card, snd:S.snd}) };
}