/* GameGrid — six small-game cards with per-card looping pixel sprites. */

// Game descriptions carried verbatim from the existing skipstone.co.nz site per
// brand-identity-brief §10 ("until Alex rewrites"). Tone clash vs the dry-minimal
// brand voice is known; rewrite later. All six are live and playable on their
// own subdomains.
const GAMES = [
  {
    name: "Fox Three", slug: "foxthree", hue: "#0F3142", fg: "#A2DCC7",
    img: "foxthree.png", sprite: "plane",
    desc: "tactical air combat and base management with pilot progression. build and arm your fleet, defend your airspace.",
    tag: "live",
  },
  {
    name: "Nanofarm", slug: "nanofarm", hue: "#A2DCC7", fg: "#352B42",
    img: "Nanofarm.png", sprite: "sprout",
    desc: "develop a farm, unlock crops and tools, and trade goods on the open market.",
    tag: "live",
  },
  {
    name: "Fa(r)ther", slug: "farther", hue: "#352B42", fg: "#F2F0E5",
    img: "Farther.png", sprite: "walker",
    desc: "a stripped-back, no frills RTS with a twist.",
    tag: "live",
  },
  {
    name: "Geneheart", slug: "geneheart", hue: "#EDC8C4", fg: "#352B42",
    img: "Geneheart.png", sprite: "heart",
    desc: "tamagotchi meets pokemon in this tiny yet addictive game.",
    tag: "live",
  },
  {
    name: "Terminal Tanks", slug: "terminaltanks", hue: "#1d1f24", fg: "#A2DCC7",
    img: "TerminalTanks.png", sprite: "tank",
    desc: "an homage to scorched earth, tactical tank battles in your browser.",
    tag: "live",
  },
  {
    name: "Zaci Boom", slug: "zaciboom", hue: "#E6E2D1", fg: "#352B42",
    img: "ZaciBoom.png", sprite: "boom",
    desc: "a fun game for young kids, destroy rockets, upgrade your slingshot.",
    tag: "live",
  },
];

// --- Pixel sprite drawers. Each takes (ctx, t, fg) and draws into a 32x32 area. ---
const SPRITES = {
  plane: (ctx, t, fg) => {
    // little jet that wobbles
    const wob = Math.floor(Math.sin(t * 0.18) * 2);
    ctx.fillStyle = fg;
    // body
    ctx.fillRect(8, 14 + wob, 16, 2);
    ctx.fillRect(11, 13 + wob, 10, 4);
    // wings
    ctx.fillRect(14, 11 + wob, 4, 8);
    ctx.fillRect(13, 18 + wob, 6, 2);
    // exhaust dashes
    for (let i = 0; i < 4; i++) {
      const o = (t + i * 4) % 16;
      if (o < 8) ctx.fillRect(2 + o * 0.5, 14 + wob, 2, 1);
    }
  },
  sprout: (ctx, t, fg) => {
    // sprout growing then resetting
    const phase = t % 60;
    const h = Math.min(10, Math.floor(phase / 4));
    ctx.fillStyle = fg;
    // soil
    ctx.fillRect(8, 24, 16, 2);
    // stem
    for (let i = 0; i < h; i++) {
      ctx.fillRect(15, 23 - i, 2, 1);
    }
    // leaves
    if (h >= 4) {
      ctx.fillRect(13, 22 - h + 4, 2, 1);
      ctx.fillRect(17, 22 - h + 4, 2, 1);
    }
    if (h >= 8) {
      ctx.fillRect(12, 22 - h + 7, 3, 1);
      ctx.fillRect(17, 22 - h + 7, 3, 1);
    }
  },
  walker: (ctx, t, fg) => {
    // tiny figure walking left to right, looping
    const x = (t * 0.4) % 32;
    const step = Math.floor(t / 4) % 2;
    ctx.fillStyle = fg;
    const px = Math.floor(x);
    // head
    ctx.fillRect(px + 2, 12, 2, 2);
    // body
    ctx.fillRect(px + 2, 14, 2, 4);
    // legs
    if (step === 0) {
      ctx.fillRect(px + 1, 18, 1, 2);
      ctx.fillRect(px + 4, 18, 1, 2);
    } else {
      ctx.fillRect(px + 2, 18, 1, 2);
      ctx.fillRect(px + 3, 18, 1, 2);
    }
    // ground
    ctx.fillRect(0, 21, 32, 1);
  },
  heart: (ctx, t, fg) => {
    // pulsing pixel heart
    const phase = t % 30;
    const scale = phase < 6 ? 1 : (phase < 12 ? 0 : 1);
    ctx.fillStyle = fg;
    const off = scale ? 0 : 1;
    // heart sprite (top half)
    const pixels = [
      [2,1],[3,1], [6,1],[7,1],
      [1,2],[2,2],[3,2],[4,2], [5,2],[6,2],[7,2],[8,2],
      [1,3],[2,3],[3,3],[4,3],[5,3],[6,3],[7,3],[8,3],
      [2,4],[3,4],[4,4],[5,4],[6,4],[7,4],
      [3,5],[4,5],[5,5],[6,5],
      [4,6],[5,6],
    ];
    for (const [x, y] of pixels) {
      ctx.fillRect(11 + x + off, 11 + y + off, scale ? 2 : 1, scale ? 2 : 1);
    }
  },
  tank: (ctx, t, fg) => {
    // tank rolling left to right
    const x = ((t * 0.3) % 36) - 4;
    ctx.fillStyle = fg;
    const px = Math.floor(x);
    // hull
    ctx.fillRect(px + 2, 16, 12, 4);
    // turret
    ctx.fillRect(px + 5, 13, 5, 3);
    // barrel
    ctx.fillRect(px + 10, 14, 6, 1);
    // treads
    const treadPhase = Math.floor(t / 2) % 2;
    for (let i = 0; i < 7; i++) {
      if ((i + treadPhase) % 2 === 0) {
        ctx.fillRect(px + 2 + i * 2, 20, 1, 1);
      }
    }
    ctx.fillRect(px + 2, 21, 12, 1);
  },
  boom: (ctx, t, fg) => {
    // small pixel explosion that grows then resets
    const phase = t % 28;
    const r = Math.min(phase, 10);
    ctx.fillStyle = fg;
    // center
    ctx.fillRect(16, 16, 1, 1);
    if (r > 1) {
      ctx.fillRect(16 - 1, 16, 3, 1);
      ctx.fillRect(16, 16 - 1, 1, 3);
    }
    if (r > 3) {
      ctx.fillRect(16 - 2, 16, 5, 1);
      ctx.fillRect(16, 16 - 2, 1, 5);
      ctx.fillRect(15, 15, 1, 1);
      ctx.fillRect(17, 17, 1, 1);
      ctx.fillRect(15, 17, 1, 1);
      ctx.fillRect(17, 15, 1, 1);
    }
    if (r > 6) {
      // ring
      for (let a = 0; a < 12; a++) {
        const ang = (a / 12) * Math.PI * 2;
        const ex = Math.floor(16 + Math.cos(ang) * (r - 3));
        const ey = Math.floor(16 + Math.sin(ang) * (r - 3));
        if (Math.random() < 0.85) ctx.fillRect(ex, ey, 1, 1);
      }
    }
  },
};

function SpriteCanvas({ spriteKey, fg, running = true }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const cv = ref.current;
    if (!cv) return;
    cv.width = 32; cv.height = 32;
    const ctx = cv.getContext("2d");
    ctx.imageSmoothingEnabled = false;
    let raf;
    let t = 0;
    const draw = () => {
      ctx.clearRect(0, 0, 32, 32);
      const fn = SPRITES[spriteKey];
      if (fn) fn(ctx, t, fg);
      t += 1;
      if (running) raf = requestAnimationFrame(draw);
    };
    // run at ~24fps
    let interval;
    if (running) {
      interval = setInterval(draw, 1000 / 24);
    } else {
      draw();
    }
    return () => { cancelAnimationFrame(raf); clearInterval(interval); };
  }, [spriteKey, fg, running]);
  return <canvas ref={ref} style={{
    width: 64, height: 64, imageRendering: "pixelated", display: "block",
  }}/>;
}

function GameCard({ game }) {
  const [hover, setHover] = React.useState(false);
  const [press, setPress] = React.useState(false);

  return (
    <a href={`https://${game.slug}.skipstone.co.nz`}
       className="game-card"
       onMouseEnter={() => setHover(true)}
       onMouseLeave={() => { setHover(false); setPress(false); }}
       onMouseDown={() => setPress(true)}
       onMouseUp={() => setPress(false)}
       style={{
         display: "block",
         border: "1.5px solid var(--ss-mulberry)",
         background: "var(--ss-bone)",
         boxShadow: press ? "0 0 0 var(--ss-mulberry)" : "2px 2px 0 var(--ss-mulberry)",
         textDecoration: "none",
         color: "inherit",
         position: "relative",
       }}>
      <div style={{
        aspectRatio: "1 / 1",
        background: game.hue,
        borderBottom: "1.5px solid var(--ss-mulberry)",
        position: "relative",
        overflow: "hidden",
      }}>
        {/* Real thumbnail */}
        {game.img && (
          <img src={`assets/photos/${game.img}`} alt=""
               className="pixelated"
               style={{
                 position: "absolute", inset: 0,
                 width: "100%", height: "100%",
                 objectFit: "cover",
                 imageRendering: "pixelated",
                 opacity: hover ? 1 : 0,
                 transition: "opacity 220ms steps(3, end)",
                 zIndex: 1,
               }}/>
        )}
        {/* Default: title + animated sprite */}
        <div style={{
          position: "absolute", inset: 0,
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          justifyContent: "center",
          padding: 14,
          opacity: hover && game.img ? 0 : 1,
          transition: "opacity 180ms steps(3, end)",
          zIndex: 0,
        }}>
          <SpriteCanvas spriteKey={game.sprite} fg={game.fg} running={true}/>
          <div style={{
            fontFamily: "Filepile, cursive",
            fontSize: 30,
            lineHeight: 0.9,
            color: game.fg,
            textAlign: "center",
            marginTop: 12,
          }}>{game.name}</div>
        </div>

        {/* tag chip — top right */}
        <div className="pixel-text" style={{
          position: "absolute",
          top: 8, right: 8,
          fontFamily: "basis33, monospace",
          fontSize: 11,
          letterSpacing: "0.14em",
          textTransform: "uppercase",
          padding: "3px 6px 1px",
          background: hover ? "var(--ss-bone)" : "rgba(53,43,66,0.6)",
          color: hover ? "var(--ss-mulberry)" : "var(--ss-bone)",
          border: "1px solid",
          borderColor: hover ? "var(--ss-mulberry)" : "transparent",
          zIndex: 2,
          transition: "background 120ms ease, color 120ms ease",
        }}>{game.tag}</div>

        {/* play arrow on hover */}
        <div className="pixel-text" style={{
          position: "absolute",
          bottom: 8, right: 8,
          fontFamily: "basis33, monospace",
          fontSize: 12,
          letterSpacing: "0.14em",
          textTransform: "uppercase",
          padding: "3px 7px 1px",
          background: "var(--ss-mint)",
          color: "var(--ss-navy)",
          border: "1.5px solid var(--ss-navy)",
          boxShadow: "2px 2px 0 var(--ss-navy)",
          zIndex: 3,
          opacity: hover ? 1 : 0,
          transform: hover ? "translate(0,0)" : "translate(2px, 2px)",
          transition: "opacity 120ms steps(2,end), transform 120ms steps(2,end)",
        }}>play&nbsp;↗</div>
      </div>

      <div style={{ padding: "12px 14px 14px" }}>
        <div className="pixel-text">
          <span style={{
            fontFamily: "basis33, monospace",
            fontSize: 17,
            color: "var(--ss-navy)",
            lineHeight: 1.3,
          }}>{game.name.toLowerCase()}</span>
        </div>
        <div className="pixel-text" style={{
          fontFamily: "basis33, monospace",
          fontSize: 13,
          color: "var(--ss-mulberry)",
          lineHeight: 1.4,
          marginTop: 4,
        }}>{game.desc}</div>
        <div className="pixel-text" style={{
          fontFamily: "basis33, monospace",
          fontSize: 12,
          color: "var(--ss-navy)",
          letterSpacing: "0.06em",
          marginTop: 8,
          opacity: 0.75,
        }}>{game.slug}.skipstone.co.nz&nbsp;↗</div>
      </div>
    </a>
  );
}

function GameGrid() {
  return (
    <section id="shelf" style={{ marginBottom: 64 }}>
      <div className="section-head">
        <span className="num">02</span>
        <span className="label">on the shelf</span>
        <span className="rule" style={{
          height: 0, borderBottom: "1px dashed color-mix(in oklab, var(--ss-mulberry) 35%, transparent)"
        }}/>
        <span className="label" style={{ color: "var(--ss-mulberry)" }}>six small games</span>
      </div>
      <div className="shelf-row">
        {GAMES.map(g => <GameCard key={g.slug} game={g}/>)}
      </div>
    </section>
  );
}

window.GameGrid = GameGrid;
