// 2D HUD overlay (drawn in CSS px on the #hud canvas above the GL world): meters, белочка drunk
// vignette + double-vision, banners, the squirrel taunt, and the menu / death / win screens.
import { hud } from './context.js';
import { player, view, state, squirrel } from '../state.js';
import { UPGRADES } from '../config.js';
import { clamp } from '../lib/math.js';

export var hudRects = { play: null, retry: null };
export var upRects = [];
export var bomzharaArtStatus = { loaded: false, error: false, src: '', deathLoaded: false, deathError: false, deathSrc: '' };
var SQUIRREL_LINES = [
  'не отдавай мне последнюю...',
  'мы с тобой одно, браток.',
  'ещё по одной?',
  'я тут навсегда живу.',
];
var HORRORS = [
  { id: 'blackout', name: 'ТЕМНОТА', desc: 'края комнаты лезут внутрь' },
  { id: 'possessed', name: 'ЗАЛИПШАЯ КЛАВИША', desc: 'одна сторона держится сама' },
  { id: 'window', name: 'ОТКРЫТОЕ ОКНО', desc: 'снег зовёт наружу' },
];
var bomzharaArt = null;
var bomzharaDeathArt = null;

if (typeof Image !== 'undefined') {
  bomzharaArt = new Image();
  bomzharaArt.decoding = 'async';
  bomzharaArt.onload = function () { bomzharaArtStatus.loaded = true; };
  bomzharaArt.onerror = function () { bomzharaArtStatus.error = true; };
  bomzharaArtStatus.src = new URL('../assets/final/bomzhara_toast_builtin_b_painterly.png', import.meta.url).href;
  bomzharaArt.src = bomzharaArtStatus.src;

  bomzharaDeathArt = new Image();
  bomzharaDeathArt.decoding = 'async';
  bomzharaDeathArt.onload = function () { bomzharaArtStatus.deathLoaded = true; };
  bomzharaDeathArt.onerror = function () { bomzharaArtStatus.deathError = true; };
  bomzharaArtStatus.deathSrc = new URL('../assets/final/bomzhara_death_broken_glass_painterly.png', import.meta.url).href;
  bomzharaDeathArt.src = bomzharaArtStatus.deathSrc;
}

function bar(x, y, w, h, frac, r, g, b, label, val) {
  var c = hud;
  c.fillStyle = 'rgba(255,255,255,0.10)'; rr(c, x, y, w, h, h / 2); c.fill();
  frac = clamp(frac, 0, 1);
  if (frac > 0) { c.fillStyle = 'rgb(' + r + ',' + g + ',' + b + ')'; rr(c, x, y, w * frac, h, h / 2); c.fill(); }
  c.fillStyle = '#fff'; c.font = 'bold 11px ui-monospace,monospace'; c.textAlign = 'left'; c.textBaseline = 'middle';
  c.fillText(label, x + 2, y - 9);
  if (val != null) { c.textAlign = 'right'; c.fillText(val, x + w - 2, y - 9); }
}
function rr(c, x, y, w, h, r) { r = Math.min(r, w / 2, h / 2); c.beginPath(); c.moveTo(x + r, y); c.arcTo(x + w, y, x + w, y + h, r); c.arcTo(x + w, y + h, x, y + h, r); c.arcTo(x, y + h, x, y, r); c.arcTo(x, y, x + w, y, r); c.closePath(); }

function drawImageCover(c, img, x, y, w, h) {
  var sw = img.naturalWidth || img.width, sh = img.naturalHeight || img.height;
  if (!sw || !sh) return;
  var srcRatio = sw / sh, dstRatio = w / h, sx = 0, sy = 0, ssw = sw, ssh = sh;
  if (srcRatio > dstRatio) { ssw = sh * dstRatio; sx = (sw - ssw) * 0.5; }
  else { ssh = sw / dstRatio; sy = (sh - ssh) * 0.5; }
  c.drawImage(img, sx, sy, ssw, ssh, x, y, w, h);
}

function drawBomzharaPortrait(W, H, mode) {
  var dead = mode === 'dead';
  var img = dead ? bomzharaDeathArt : bomzharaArt;
  if (!img || (dead ? !bomzharaArtStatus.deathLoaded : !bomzharaArtStatus.loaded)) return;
  var c = hud, wide = W >= 760 && H >= 440;
  var size = wide ? clamp(H * 0.38, 168, 250) : clamp(Math.min(W * 0.38, H * 0.23), 88, 150);
  var x = wide ? clamp(W / 2 - size - 260, 24, W - size - 24) : W / 2 - size / 2;
  var y = wide ? H / 2 - size / 2 - (mode === 'end' || dead ? 34 : 8) : 18;
  c.save();
  c.shadowColor = 'rgba(255,210,61,0.42)';
  c.shadowBlur = 22;
  c.fillStyle = 'rgba(15,10,7,0.78)';
  rr(c, x - 7, y - 7, size + 14, size + 14, 8); c.fill();
  c.shadowBlur = 0;
  rr(c, x, y, size, size, 6); c.clip();
  drawImageCover(c, img, x, y, size, size);
  c.restore();
  c.save();
  c.strokeStyle = 'rgba(255,210,61,0.62)';
  c.lineWidth = 2;
  rr(c, x, y, size, size, 6); c.stroke();
  c.restore();
}

function button(label, cx, cy, w, h, accent) {
  var c = hud, x = cx - w / 2, y = cy - h / 2;
  c.save(); c.shadowColor = accent; c.shadowBlur = 18; c.fillStyle = accent; rr(c, x, y, w, h, h / 2); c.fill(); c.restore();
  c.fillStyle = '#120a06'; c.font = 'bold 20px ui-monospace,monospace'; c.textAlign = 'center'; c.textBaseline = 'middle';
  c.fillText(label, cx, cy + 1);
  return { x: x, y: y, w: w, h: h };
}

export function renderHud() {
  var c = hud, W = view.cssW, H = view.cssH;
  c.setTransform(view.dpr, 0, 0, view.dpr, 0, 0);
  c.clearRect(0, 0, W, H);
  var warp = state.warp;

  // ---- peripheral dread: the single bulb lights the centre; the edges fall into a crawling dark ----
  if (state.mode !== 'MENU') {
    var vg = c.createRadialGradient(W / 2, H * 0.5, Math.min(W, H) * 0.22, W / 2, H * 0.5, Math.max(W, H) * 0.66);
    vg.addColorStop(0, 'rgba(0,0,0,0)');
    vg.addColorStop(1, 'rgba(2,1,3,0.82)');
    c.fillStyle = vg; c.fillRect(0, 0, W, H);
    // "кажется, что кто-то постоянно рядом" - faint shapes drift at the very edge as белочка rises
    if (warp > 0.25 && state.mode === 'PLAY') {
      c.fillStyle = 'rgba(0,0,0,' + (0.45 * warp).toFixed(3) + ')';
      for (var pi = 0; pi < 3; pi++) {
        var pa = state.t * 0.25 + pi * 2.1;
        var pxv = W / 2 + Math.cos(pa) * W * 0.6, pyv = H / 2 + Math.sin(pa * 1.3) * H * 0.56;
        c.beginPath(); c.ellipse(pxv, pyv, 34, 58, 0, 0, Math.PI * 2); c.fill();
      }
    }
  }

  // Siren helps: the ambulance strobe cuts through hallucinations and marks the real bodies.
  if ((state.sirenPulse > 0 || state.ambulancePulse > 0) && state.mode === 'PLAY') {
    var sp = Math.max(state.sirenPulse, state.ambulancePulse);
    c.fillStyle = Math.sin(state.t * 22) > 0 ? 'rgba(255,20,40,' + (0.05 + sp * 0.06).toFixed(3) + ')' : 'rgba(35,110,255,' + (0.05 + sp * 0.06).toFixed(3) + ')';
    c.fillRect(0, 0, W, H);
  }

  // Blackout blocks: crawling dark shapes hide the playfield, but the HUD is drawn after this.
  if (state.blackoutPulse > 0 && state.mode === 'PLAY') {
    var bp = state.blackoutPulse;
    c.fillStyle = 'rgba(0,0,0,' + (0.24 + bp * 0.32).toFixed(3) + ')';
    c.fillRect(0, 0, W, H);
    c.fillStyle = 'rgba(0,0,0,' + (0.46 + bp * 0.34).toFixed(3) + ')';
    for (var sh = 0; sh < 6; sh++) {
      var a = state.t * (0.42 + sh * 0.04) + sh * 1.7;
      var side = sh % 4;
      var sx = side === 0 ? -26 : (side === 1 ? W + 26 : W * (0.18 + 0.64 * ((Math.sin(a) + 1) * 0.5)));
      var sy = side === 2 ? -34 : (side === 3 ? H + 34 : H * (0.16 + 0.68 * ((Math.cos(a * 1.3) + 1) * 0.5)));
      c.beginPath();
      c.ellipse(sx, sy, 62 + 20 * Math.sin(a * 1.9), 150 + 30 * Math.cos(a), a, 0, Math.PI * 2);
      c.fill();
    }
    var hole = c.createRadialGradient(W / 2, H * 0.52, Math.min(W, H) * 0.12, W / 2, H * 0.52, Math.min(W, H) * 0.34);
    hole.addColorStop(0, 'rgba(255,255,255,' + (0.11 * bp).toFixed(3) + ')');
    hole.addColorStop(1, 'rgba(255,255,255,0)');
    c.fillStyle = hole; c.fillRect(0, 0, W, H);
  }

  if (state.weirdKind === 'possessed' && state.mode === 'PLAY') drawPossessedKey(W, H);
  if (state.weirdKind === 'window' && state.mode === 'PLAY') drawWindSound(W, H);

  // ---- белочка drunk overlay (the world swims as you lose your mind) ----
  if (warp > 0.02 && state.mode === 'PLAY') {
    var pulse = 0.5 + 0.5 * Math.sin(state.t * 4);
    var g = c.createRadialGradient(W / 2, H / 2, Math.min(W, H) * 0.25, W / 2, H / 2, Math.max(W, H) * 0.62);
    g.addColorStop(0, 'rgba(0,0,0,0)');
    g.addColorStop(1, 'rgba(' + (40 + warp * 120) + ',0,' + (60 + warp * 80) + ',' + (0.35 * warp + 0.12 * warp * pulse).toFixed(3) + ')');
    c.fillStyle = g; c.fillRect(0, 0, W, H);
  }

  if (state.mode === 'PLAY' || state.mode === 'DEAD' || state.mode === 'WIN' || state.mode === 'UPGRADE') drawMeters(W, H, warp);

  // squirrel taunt
  if (squirrel.active && squirrel.talkT > 0 && state.mode === 'PLAY') {
    c.fillStyle = 'rgba(255,255,255,0.92)'; c.font = 'italic 13px ui-monospace,monospace'; c.textAlign = 'center'; c.textBaseline = 'bottom';
    c.fillText(SQUIRREL_LINES[squirrel.line], clamp(squirrel.x, 80, W - 80), squirrel.y - 30);
  }

  // banner
  if (state.bannerT > 0 && state.mode === 'PLAY') {
    c.globalAlpha = clamp(state.bannerT, 0, 1);
    c.fillStyle = '#ffd23d'; c.font = 'bold 16px ui-monospace,monospace'; c.textAlign = 'center'; c.textBaseline = 'middle';
    c.fillText(state.banner, W / 2, state.warp > 0.3 ? 120 : 104);
    c.globalAlpha = 1;
  }

  if (state.mode === 'MENU') drawMenu(W, H);
  else if (state.mode === 'DEAD') drawEnd(W, H, false);
  else if (state.mode === 'WIN') drawEnd(W, H, true);
  else if (state.mode === 'UPGRADE') drawUpgrade(W, H);
}

function drawMeters(W, H, warp) {
  var c = hud, m = 14, bw = (W - m * 2 - 10) * 0.5;
  // XP progress (thin line at the very top edge)
  var xf = state.xpNext > 0 ? state.xp / state.xpNext : 0;
  c.fillStyle = 'rgba(255,255,255,0.08)'; c.fillRect(0, 0, W, 3);
  c.fillStyle = '#ffd23d'; c.fillRect(0, 0, W * clamp(xf, 0, 1), 3);
  // VODKA = ammo AND sanity
  bar(m, 30, bw, 12, player.vodka / player.maxVodka, 240, 180, 60, 'ВОДКА / РАССУДОК', Math.ceil(player.vodka));
  // HP = blood (you fire it when the bottle's dry)
  bar(m + bw + 10, 30, bw, 12, player.hp / player.maxHp, 210, 40, 40, 'КРОВЬ', Math.ceil(player.hp));
  // белочка = madness meter (fills toward 1 = you lose)
  bar(m, 58, W - m * 2, 8, player.belochka, 200, 40, 230, 'БЕЛОЧКА', '');
  // score + clock
  c.fillStyle = '#cdb'; c.font = 'bold 12px ui-monospace,monospace'; c.textAlign = 'left'; c.textBaseline = 'top';
  c.fillText('УР.' + state.level + '   ТРУПОВ: ' + state.kills, m, 72);
  drawAbilityMarks(m, 91);
  c.textAlign = 'right';
  var left = Math.max(0, Math.ceil(state.goalTime - state.survived));
  c.fillStyle = left <= 10 ? '#ffd23d' : '#cdb';
  c.fillText('ДО СКОРОЙ: ' + left + 'с', W - m, 72);
}

function drawAbilityMarks(x, y) {
  var c = hud, n = 0;
  function mark(r, g, b, count, shape) {
    var cx = x + n * 30 + 8, cy = y;
    c.save();
    c.globalAlpha = 0.82;
    c.strokeStyle = 'rgb(' + r + ',' + g + ',' + b + ')';
    c.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',0.18)';
    c.lineWidth = 2;
    c.beginPath();
    if (shape === 1) c.rect(cx - 6, cy - 6, 12, 12);
    else if (shape === 2) { c.moveTo(cx, cy - 8); c.lineTo(cx + 8, cy); c.lineTo(cx, cy + 8); c.lineTo(cx - 8, cy); c.closePath(); }
    else c.arc(cx, cy, 7, 0, Math.PI * 2);
    c.fill(); c.stroke();
    c.globalAlpha = 1;
    c.fillStyle = '#e8dcc8'; c.font = 'bold 10px ui-monospace,monospace'; c.textAlign = 'left'; c.textBaseline = 'middle';
    c.fillText(String(count), cx + 10, cy + 1);
    c.restore();
    n++;
  }
  if (player.up.molotov > 0) mark(255, 94, 18, player.up.molotov, 2);
  if (player.up.ricochetSeek > 0) mark(255, 210, 61, player.up.ricochetSeek, 0);
  if (player.up.shieldMax > 0) mark(140, 220, 255, player.shield + '/' + player.up.shieldMax, 1);
  if (player.up.ambulance > 0) mark(255, 55, 90, player.up.ambulance, 0);
}

function drawMenu(W, H) {
  var c = hud;
  c.fillStyle = 'rgba(6,5,4,0.7)'; c.fillRect(0, 0, W, H);
  drawBomzharaPortrait(W, H, 'menu');
  var split = W >= 760 && H >= 440 && bomzharaArtStatus.loaded;
  var cx = split ? clamp(W / 2 + 130, W / 2, W - 260) : W / 2;
  var copyW = split ? Math.max(260, Math.min(500, W - cx - 32)) : W - 70;
  c.textAlign = 'center'; c.textBaseline = 'middle';
  c.save(); c.shadowColor = 'rgba(200,40,230,0.6)'; c.shadowBlur = 24;
  c.fillStyle = '#fff'; c.font = 'bold 30px ui-monospace,monospace'; c.fillText('BULLET HELL', cx, H / 2 - 96);
  c.fillStyle = '#ffd23d'; c.font = 'bold 40px ui-monospace,monospace'; c.fillText('БОМЖАРА', cx, H / 2 - 56);
  c.restore();
  c.fillStyle = '#b8a' ; c.font = '13px ui-monospace,monospace';
  wrap(c, 'твоя кровь - наполовину водка. продержись до скорой, но оставь глоток себе - иначе белочка заберёт.', cx, H / 2 - 18, copyW, 18);
  hudRects.play = button('НАЛИВАЙ', cx, H / 2 + 56, 240, 56, '#ffd23d');
  if (state.best > 0) { c.fillStyle = '#776'; c.font = '12px ui-monospace,monospace'; c.fillText('рекорд трупов: ' + state.best, cx, H / 2 + 104); }
  drawHorrorList(W, H);
}

function drawEnd(W, H, win) {
  var c = hud;
  c.fillStyle = 'rgba(6,5,4,0.82)'; c.fillRect(0, 0, W, H);
  drawBomzharaPortrait(W, H, win ? 'end' : 'dead');
  c.textAlign = 'center'; c.textBaseline = 'middle';
  var split = W >= 760 && H >= 440 && (win ? bomzharaArtStatus.loaded : bomzharaArtStatus.deathLoaded);
  var cx = split ? clamp(W / 2 + 130, W / 2, W - 260) : W / 2;
  var copyW = split ? Math.max(260, Math.min(500, W - cx - 32)) : W - 70;
  var title, sub, col;
  if (win && state.endReason === 'sane') { title = 'ДОЖИЛ ДО СКОРОЙ'; sub = 'мигалки в окне. ты оставил себе глоток, и тебя ещё можно собрать.'; col = '#7dffa6'; }
  else if (win) { title = 'СКОРАЯ ПРИЕХАЛА'; sub = 'нечисть мертва, бутылка тоже. фельдшер смотрит молча.'; col = '#ffd23d'; }
  else if (state.endReason === 'madness') { title = 'БЕЛОЧКА ПОБЕДИЛА'; sub = 'ты выпил рассудок до дна. теперь вы с ней - одно.'; col = '#c828e6'; }
  else if (state.endReason === 'window') { title = 'ВЫШЕЛ В ОКНО'; sub = 'ветер был как голос. скорая приехала уже зря.'; col = '#9bc8ff'; }
  else { title = 'ИСТЁК'; sub = 'кровь кончилась раньше водки. так тоже бывает.'; col = '#e64545'; }
  c.save(); c.shadowColor = col; c.shadowBlur = 22; c.fillStyle = col; c.font = 'bold 26px ui-monospace,monospace';
  c.fillText(title, cx, H / 2 - 70); c.restore();
  c.fillStyle = '#cbb'; c.font = '13px ui-monospace,monospace';
  wrap(c, sub, cx, H / 2 - 30, copyW, 18);
  c.fillStyle = '#cdb'; c.font = 'bold 14px ui-monospace,monospace';
  c.fillText('ТРУПОВ: ' + state.kills + '    ПРИЗРАКОВ: ' + state.phantoms, cx, H / 2 + 6);
  hudRects.retry = button('ЕЩЁ ПО ОДНОЙ', cx, H / 2 + 54, 250, 54, col);
}

function drawUpgrade(W, H) {
  var c = hud;
  c.fillStyle = 'rgba(6,5,4,0.92)'; c.fillRect(0, 0, W, H);
  c.textAlign = 'center'; c.textBaseline = 'alphabetic';
  c.fillStyle = '#5dffa6'; c.font = 'bold 13px ui-monospace,monospace';
  c.fillText('УРОВЕНЬ ' + state.level, W / 2, 116);
  c.save(); c.shadowColor = 'rgba(255,210,61,0.5)'; c.shadowBlur = 18;
  c.fillStyle = '#fff'; c.font = 'bold 26px ui-monospace,monospace';
  c.fillText('ОПОХМЕЛИСЬ', W / 2, 146); c.restore();
  upRects = [];
  var n = state.upChoices.length, top = 172, ch = Math.min((H - top - 24) / n - 10, 112), cw = Math.min(W - 40, 460), cx0 = W / 2 - cw / 2;
  for (var i = 0; i < n; i++) {
    var u = UPGRADES[state.upChoices[i]], y = top + i * (ch + 10);
    c.save(); c.shadowColor = '#ffd23d'; c.shadowBlur = 12;
    c.fillStyle = 'rgba(22,18,12,0.96)'; rr(c, cx0, y, cw, ch, 12); c.fill(); c.restore();
    c.lineWidth = 2; c.strokeStyle = '#ffd23d'; rr(c, cx0, y, cw, ch, 12); c.stroke();
    c.textAlign = 'left'; c.fillStyle = '#ffd23d'; c.font = 'bold 18px ui-monospace,monospace';
    c.fillText(u.ru, cx0 + 16, y + ch * 0.44);
    c.fillStyle = '#c8d2ee'; c.font = '13px ui-monospace,monospace';
    c.fillText(u.de, cx0 + 16, y + ch * 0.72);
    upRects.push({ x: cx0, y: y, w: cw, h: ch });
  }
  c.textAlign = 'left';
}

function wrap(c, text, cx, y, maxW, lh) {
  var words = text.split(' '), line = '', lines = [];
  c.textAlign = 'center'; c.textBaseline = 'middle';
  for (var i = 0; i < words.length; i++) { var t = line ? line + ' ' + words[i] : words[i]; if (c.measureText(t).width > maxW && line) { lines.push(line); line = words[i]; } else line = t; }
  if (line) lines.push(line);
  for (var j = 0; j < lines.length; j++) c.fillText(lines[j], cx, y + j * lh);
}

function drawPossessedKey(W, H) {
  var c = hud, x = W - 92, y = H * 0.5 - 42;
  var label = state.possessedX > 0 ? 'D' : (state.possessedX < 0 ? 'A' : (state.possessedY < 0 ? 'W' : 'S'));
  c.save();
  c.globalAlpha = 0.9;
  c.shadowColor = '#ffd23d'; c.shadowBlur = 16;
  c.fillStyle = 'rgba(22,18,8,0.82)'; rr(c, x, y, 68, 68, 10); c.fill();
  c.strokeStyle = '#ffd23d'; c.lineWidth = 3; rr(c, x, y, 68, 68, 10); c.stroke();
  c.fillStyle = '#ffd23d'; c.font = 'bold 38px ui-monospace,monospace'; c.textAlign = 'center'; c.textBaseline = 'middle';
  c.fillText(label, x + 34, y + 36);
  c.strokeStyle = 'rgba(255,210,61,0.55)'; c.lineWidth = 2;
  for (var i = 0; i < 4; i++) {
    c.beginPath();
    c.moveTo(x + 34, y + 68);
    c.quadraticCurveTo(x + 18 + i * 12, y + 100 + Math.sin(state.t * 7 + i) * 10, x - 36 + i * 28, y + 136);
    c.stroke();
  }
  c.restore();
}

function drawWindSound(W, H) {
  var c = hud, p = state.windowPulse || 0.4;
  c.save();
  c.globalAlpha = 0.45 + p * 0.35;
  c.fillStyle = '#dcefff'; c.font = 'bold 18px ui-monospace,monospace'; c.textAlign = 'center'; c.textBaseline = 'middle';
  c.fillText('ууууууу', W / 2 + Math.sin(state.t * 4) * 18, 126 + Math.sin(state.t * 8) * 4);
  c.strokeStyle = 'rgba(220,240,255,0.45)'; c.lineWidth = 2;
  for (var i = 0; i < 5; i++) {
    var yy = 150 + i * 34 + Math.sin(state.t * 5 + i) * 12;
    c.beginPath();
    c.moveTo(W * 0.25, yy);
    c.bezierCurveTo(W * 0.38, yy - 22, W * 0.54, yy + 22, W * 0.72, yy - 10);
    c.stroke();
  }
  c.restore();
}

function drawHorrorList(W, H) {
  var c = hud, seen = [], i;
  for (i = 0; i < HORRORS.length; i++) if (state.horrorSeen[HORRORS[i].id]) seen.push(HORRORS[i]);
  if (!seen.length) return;
  var w = Math.min(560, W - 40), x = W / 2 - w / 2, y = Math.min(H - 122, H / 2 + 134);
  c.save();
  c.fillStyle = 'rgba(0,0,0,0.46)'; rr(c, x, y, w, 92, 8); c.fill();
  c.strokeStyle = 'rgba(255,210,61,0.32)'; c.lineWidth = 1; rr(c, x, y, w, 92, 8); c.stroke();
  c.textAlign = 'left'; c.textBaseline = 'alphabetic';
  c.fillStyle = '#ffd23d'; c.font = 'bold 12px ui-monospace,monospace';
  c.fillText('ПЕРЕЖИТЫЕ УЖАСЫ', x + 14, y + 21);
  for (i = 0; i < Math.min(seen.length, 3); i++) {
    var yy = y + 42 + i * 18;
    c.fillStyle = '#fff'; c.font = 'bold 12px ui-monospace,monospace'; c.fillText(seen[i].name, x + 14, yy);
    c.fillStyle = '#9ea8bb'; c.font = '11px ui-monospace,monospace'; c.fillText(seen[i].desc, x + 238, yy);
  }
  c.restore();
}
