// pixel-ui.jsx — 16-bit chrome for Homechella.
// Exports components on `window` so other Babel scripts can use them.

const { useEffect, useRef, useState, useMemo } = React;

// ─────────────────────────────────────────────────────────────────────────────
// Pixel sprite helper. Pass a string grid; "." = transparent, each other
// non-newline char = lookup into the palette object.
//
//   <PixelSprite scale={4} palette={{ "#": "#fff", "*": "#ff0" }} grid={`
//     ..###..
//     .#***#.
//     #**#**#
//   `} />
function PixelSprite({ grid, palette, scale = 4, ariaLabel }) {
  const rows = grid.trim().split("\n").map((r) => r.replace(/\s+$/, ""));
  const h = rows.length;
  const w = Math.max(...rows.map((r) => r.length));
  const rects = [];
  for (let y = 0; y < h; y++) {
    for (let x = 0; x < rows[y].length; x++) {
      const ch = rows[y][x];
      if (ch === "." || ch === " ") continue;
      const fill = palette[ch];
      if (!fill) continue;
      rects.push(
        <rect key={`${x},${y}`} x={x} y={y} width="1" height="1" fill={fill} />
      );
    }
  }
  return (
    <svg
      width={w * scale}
      height={h * scale}
      viewBox={`0 0 ${w} ${h}`}
      style={{ imageRendering: "pixelated", display: "block" }}
      shapeRendering="crispEdges"
      role="img"
      aria-label={ariaLabel || ""}
    >
      {rects}
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Library of channel/genre glyph sprites.

const GLYPHS = {
  // Electric guitar — vertical, Les-Paul-ish body with pickguard, pickups, knobs.
  guitar: {
    palette: {
      "o": "#0a0218", "K": "#1b0a2e",
      "R": "#ff5cf2", "r": "#c534b8", "p": "#7a1a8a",
      "w": "#fff8c2", "c": "#bdb27a",
      "y": "#ffd23f", "g": "#a07020",
      "N": "#7a3aa1", "n": "#a25fc4", "F": "#cfa9e6",
      "S": "#e0e0eb",
    },
    grid: `
.........oo........
........oRRRo......
........oRrRo......
........oSSSo......
........oRRRo......
........orrro......
.........ooo.......
........oWWWo......
........oNnNo......
........oFFFo......
........oNnNo......
........oFFFo......
........oNnNo......
........oFFFo......
........oNnNo......
........oFFFo......
.......ooNnNoo.....
......oRRRNNRRRo...
.....oRRrcwwcrRRo..
....oRRrwwwwwwrRRo.
....oRRwwwwwwwwRRo.
....oRwSSSwwSSSwRo.
....oRrygrrrrgyrRo.
....oRrygrrrrgyrRo.
....oRRryrrrryrRRo.
.....oRRrrrrrrRRo..
......oRRRrRRRRo...
.......oRRRRRo.....
........ooooo......`,
  },
  // Classic '80s boombox — handle, twin speakers, cassette deck, buttons.
  boombox: {
    palette: {
      "o": "#0a0218",
      "y": "#ffd23f", "Y": "#fff066", "g": "#a07020",
      "K": "#1b0a2e", "k": "#3a2154",
      "S": "#9da6b5", "s": "#535c70", "H": "#d8dee9",
      "r": "#ff5cf2", "R": "#a834a8",
      "w": "#fff8c2",
    },
    grid: `
............oo............
...........oSSo...........
...........oSHo...........
...........oSso...........
...........oSso...........
...........oSso...........
.......ooooosKsoooo.......
......oyYYYYYYYYYYYyo.....
.....oyYYYHHHHHHHHHYYyo...
....oyYyyyyyyyyyyyyyyyyo..
....oyKkkkkkkkkkkkkkkKyo..
....oyKsSSSskwwksSSSsKyo..
....oyKsSHSskwwksSHSsKyo..
....oyKsSSSskwwksSSSsKyo..
....oyKssssskkkksssssKyo..
....oyKKKKKKkkkkKKKKKKyo..
....oyKkkkkkkkkkkkkkkKyo..
....oyKkrkkrkkrkkrkkkKyo..
....oyKkrkkrkkrkkrkkkKyo..
....oyyyyyyyyyyyyyyyyyyo..
.....ooooooooooooooooo....`,
  },
  // Cassette tape — front view with reels showing through windows.
  cassette: {
    palette: {
      "o": "#0a0218",
      "c": "#7be0ff", "C": "#a3eaff", "d": "#3a8eb8",
      "w": "#fff8c2", "W": "#ffffff",
      "k": "#1b0a2e", "K": "#000",
      "r": "#a48cff", "p": "#ff5cf2",
    },
    grid: `
............................
.oCCCCCCCCCCCCCCCCCCCCCCCCo.
oCccccccccccccccccccccccccCo
oCcwwwwwwwwwwwwwwwwwwwwwwcCo
oCcwWWWWWWWWWWWWWWWWWWWWcwCo
oCcwWkWkWkWkWkWkWkWkWkkWcwCo
oCcwWWWWWWWWWWWWWWWWWWWWcwCo
oCcwwrrrrrrrrrrrrrrrrwwwcCo
oCccccccccccccccccccccccccCo
oCckkkkkkkkkkkkkkkkkkkkkkcCo
oCckKKKKKkkkkkkkkKKKKKkkkcCo
oCckKWKKKkkkkkkkkKKKWKkkkcCo
oCckKKKWKkkpppppkKWKKKkkkcCo
oCckKKKKKkkpppppkKKKKKkkkcCo
oCckkkkkkkkkkkkkkkkkkkkkkcCo
oCcccccccccccccccccccccccCo.
.oCCCCCCCCCCCCCCCCCCCCCCCCo.
....oo..............oo......`,
  },
  // Turntable — top-down with platter, vinyl, tonearm, pitch slider.
  deck: {
    palette: {
      "o": "#0a0218",
      "K": "#0a0a14", "k": "#1b0a2e", "S": "#4a4a5e",
      "p": "#a48cff", "P": "#c4adff", "q": "#5e3aa1",
      "y": "#ffd23f", "r": "#ff5cf2",
      "H": "#d8dee9", "M": "#8e95a8",
      "w": "#fff8c2",
    },
    grid: `
............................
.oKKKKKKKKKKKKKKKKKKKKKKKKKo.
oKkkkkkkkkkkkkkkkkkkkkkkkkkKo
oKkkkkooooooooookkkkkkSMSSkKo
oKkkoookkkkkkkkooookkkkkkkkKo
oKkookKKKKKKKKKKKkookkkSMSSkKo
oKkokKKpppppppppKKkokkkkkkkkKo
oKkokKpPPPPPPPPpPKkokkkkSSSSkKo
oKkokKpPyyyyyyyyPKkokkkkkkkkKo
oKkokKpPyywwwyyPKkokkSSSSSSkKo
oKkokKpPyywrwyyPKkokkkkkkkkkKo
oKkokKpPyywwwyyPKkokkSSSSSSkKo
oKkokKpPyyyyyyyyPKkokkkkkkkkKo
oKkokKppPPPPPPPPpKkokkSSSSSSkKo
oKkokKKpppppppppKKkokkkkkkkkKo
oKkookKKKKKKKKKKKkookkkkkkkkKo
oKkkoookkkkkkkkooookkkkkrkkkKo
oKkkkkooooooooookkkkkkkkkkkkKo
oKkkkkkkkkkkkkkkkkkkkkkkkkkKo
.oKKKKKKKKKKKKKKKKKKKKKKKKKo.`,
  },
  // Pair of maracas — two bulbs with crossed handles below.
  maracas: {
    palette: {
      "o": "#0a0218",
      "O": "#ff8a3d", "Q": "#ffb87a", "U": "#a04e1a",
      "y": "#ffd23f", "Y": "#fff8c2",
      "p": "#7a3aa1", "P": "#a25fc4",
      "k": "#1b0a2e",
    },
    grid: `
...oooo......oooo....
..oOOQQo....oQQOOo...
.oOQQQQQo..oQQQQQQo..
.oOQyyQQo..oQQyyOOo..
oOOQyYYQQooQQYYyQOOo.
oOOQQyyQQooQQyyQQOOo.
oOOQQQQQQooQQQQQQOOo.
oOOQQUUQQooQQUUQQOOo.
.oOQQUUQQooQQUUQQOo..
.oOOQUUQQooQQUUQOOo..
..oOOUUUUooUUUUOOo...
...oOOUUUooUUUUOo....
.....opUUooUUpo......
......opUooUpo.......
.......opUUpo........
........opPo.........
........opPo.........
.........op..........`,
  },
  // Microphone — round mesh head on grip with cable.
  mic: {
    palette: {
      "o": "#0a0218",
      "p": "#ff6fb5", "P": "#ffa3d1", "q": "#a03268",
      "w": "#fff8c2", "W": "#ffffff",
      "k": "#1b0a2e", "K": "#000",
      "S": "#9da6b5", "H": "#d8dee9",
      "m": "#54426e",
    },
    grid: `
......oooooo......
....oopPPPPpoo....
...opPPwwwwPPpo...
..opPwHWwwHWwPpo..
..opPwWwwwwwWwPpo.
.opPwwHWwwwwHWwPpo
.opPwwwwwwwwwwwPpo
.opPpppppppppppPpo
.opPpqqqqqqqqqpPpo
..opPqqqqqqqqqPpo.
..opPqqqqqqqqqPpo.
...opPqqqqqqqPpo..
....oopPqqqPpoo...
.......oopPo......
.......ooSHo......
......oSHHHSo.....
.....oSHHHHHSo....
.....oSHkkkHSo....
......oSHHHSo.....
.......oSSo.......
........op........
........op........`,
  },
  // Vinyl record — front view with grooves and label.
  vinyl: {
    palette: {
      "o": "#0a0218",
      "K": "#0a0a14", "k": "#1f1f2c", "g": "#3a3a4a",
      "c": "#5cffd3", "C": "#8effe3", "q": "#1c8a72",
      "w": "#fff8c2", "W": "#ffffff",
    },
    grid: `
......ooooooooo......
....ooKKKKKKKKKoo....
...oKKkkkkkkkkkKKo...
..oKkkggggggggggkkKo.
.oKkgKKKKKKKKKKKKgkKo
.oKkgKkkkkkkkkkKKgkKo
oKkgKkccccccccckKgkKo
oKkgKkcCCcccccCckKgkKo
oKkgKkcCqqcccqCckKgkKo
oKkgKkccqcWqcqcckKgkKo
oKkgKkccccWccccckKgkKo
oKkgKkcCqcccqCcckKgkKo
oKkgKkcCCcccCCcckKgkKo
oKkgKkccccccccckKgkKo
.oKkgKkkkkkkkkkKKgkKo
.oKkgKKKKKKKKKKKKgkKo
..oKkkggggggggggkkKo.
...oKKkkkkkkkkkKKo...
....ooKKKKKKKKKoo....
......ooooooooo......`,
  },
  // Sun — chunkier, with corona rays.
  sun: {
    palette: {
      "y": "#ffd23f", "Y": "#fff066", "o": "#ff8a3d", "O": "#ffaa55",
      "p": "#ff5cf2", "r": "#ff2d6e", "w": "#fff8c2",
    },
    grid: `
.......yyyy.......
......yyyyyy......
.....yyyyyyyy.....
....yYYyyyyyyy....
...yYwYYyyyooyy...
..yYwwYYyyyoooy...
..yYwwYYyyooopy...
.yYwwwYYyyyoopry.
.yYwYYYyooooppry.
.yYYYYYoOOOppprry
.yyyyyooOOpppprry
.yyyyyoooppppprry
..yyyooopppprrry..
..yyooopppprrrry..
...yoopppprrrrr...
....oopppprrrr....
.....opprrrr......
.......prr........`,
  },
  // Palm tree — taller, more frond layers, textured trunk, coconuts.
  palm: {
    palette: {
      "o": "#0a0218",
      "g": "#5cffd3", "G": "#34a896", "h": "#2a7a6a", "L": "#a8ffe4",
      "b": "#7a3aa1", "B": "#3a1054", "n": "#54206e",
      "c": "#7a4020", "C": "#a05a30",
    },
    grid: `
....gg.......gg.....
...gLg......gLg.....
..gLLgg....ggLg.....
.gLLLLgg..gggLLg....
gLLLLLLGggGGGGLLg...
ghLLLLGggGGGGGLLLg..
.hhhLGGGGGGGGGLLLLg.
..hhhGGGGGGGGGGGLLg.
....GGGGGGGGGGGGGLg.
......GGGGGGGGGGGG..
........bcbCb.......
........bCcCb.......
........bcbCC.......
.......ccCcCb.......
.......bCcbCb.......
.......bcCcCB.......
.......BcCcCb.......
.......BcbCB........
......BBccCcB.......
......BBnnnBB.......
.....BBBBBBBBB......`,
  },
  star: { palette: { "y": "#fff" }, grid: `.y.\nyyy\n.y.` },
};

function ChannelGlyph({ kind, scale = 4 }) {
  const g = GLYPHS[kind] || GLYPHS.star;
  return <PixelSprite grid={g.grid} palette={g.palette} scale={scale} />;
}

// ─────────────────────────────────────────────────────────────────────────────
// Pixel border — chunky 4-corner frame using nested box-shadows.

function PixelFrame({ color = "#ff5cf2", bg = "#1b0a2e", children, style, glow = true, className }) {
  const shadow = [
    `0 0 0 4px ${color}`,
    `0 0 0 8px #1b0a2e`,
    glow ? `0 0 24px ${color}55` : "",
  ].filter(Boolean).join(",");
  return (
    <div
      className={className}
      style={{
        position: "relative",
        background: bg,
        boxShadow: shadow,
        ...style,
      }}
    >
      {children}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Marquee — pixel-style scrolling text.

function Marquee({ items, speed = 60 }) {
  // Duplicate items so the loop is seamless.
  const repeated = [...items, ...items];
  return (
    <div className="hc-marquee">
      <div className="hc-marquee-track" style={{ animationDuration: `${speed}s` }}>
        {repeated.map((it, i) => (
          <span key={i} className="hc-marquee-item">
            <span className="hc-marquee-dot" /> {it}
          </span>
        ))}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// CRT-style bezel for the player.

function CRTBezel({ children, channel, channelNo }) {
  return (
    <div className="hc-crt" style={{ "--accent": channel?.accent || "#ff5cf2" }}>
      <div className="hc-crt-screen">
        {children}
        <div className="hc-crt-scan" aria-hidden="true" />
        <div className="hc-crt-vignette" aria-hidden="true" />
      </div>
      <div className="hc-crt-bottom">
        <div className="hc-crt-brand">
          <span className="hc-crt-led" />
          <span className="hc-crt-brand-name">HOMECHELLA</span>
        </div>
        <div className="hc-crt-channel-readout">
          <span className="hc-crt-ch-label">CH</span>
          <span className="hc-crt-ch-no">{String(channelNo || "--").padStart(2, "0")}</span>
        </div>
        <div className="hc-crt-knobs">
          <span className="hc-crt-knob" />
          <span className="hc-crt-knob" />
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Floating reactions

function ReactionLayer({ bursts }) {
  return (
    <div className="hc-reactions" aria-hidden="true">
      {bursts.map((b) => (
        <span
          key={b.id}
          className="hc-react"
          style={{
            left: `${b.x}%`,
            color: b.color,
            animationDuration: `${b.dur}s`,
          }}
        >
          {b.emoji}
        </span>
      ))}
    </div>
  );
}

// Expose to global scope for other Babel scripts.
Object.assign(window, {
  PixelSprite,
  ChannelGlyph,
  PixelFrame,
  Marquee,
  CRTBezel,
  ReactionLayer,
  GLYPHS,
});
