/* ═══════════════════════════════════════════════════════════════
   PET SPRITES — 8/16 bit pixel creatures drawn on canvas
   Each sprite is defined as a 2D array where each value is
   an index into a palette. 0 = transparent.
   ═══════════════════════════════════════════════════════════════ */

// Palette-aware: sprite colors are tokens (1=outline, 2=body, 3=shade, 4=eye, 5=accent)
// We resolve to actual CSS pixel color at draw time, pulling from --fg family.

const SPRITE_SIZE = 16;

/* 4 creatures × multiple states. '.' = 0, digits = palette idx. */
const CHARS = {
  // ── Blob-like primordial creature ──
  blobby: {
    idle: [
      "................",
      "................",
      "......11111.....",
      ".....1222221....",
      "....122222221...",
      "...12242224221..",
      "..1222424242221.",
      "..1222222222221.",
      "..1222222222221.",
      "..1223333333221.",
      "...12333333321..",
      "....122333221...",
      ".....1222221....",
      "......13331.....",
      ".....1.....1....",
      "................"
    ],
    happy: [
      "................",
      "......11111.....",
      ".....1222221....",
      "....122222221...",
      "...12222222221..",
      "..12244222442.1.",
      "..1224422244221.",
      "..1222222222221.",
      "..1221221221221.",
      "..1222222222221.",
      "...12333333321..",
      "....122333221...",
      ".....1222221....",
      "......13331.....",
      ".....1.....1....",
      "................"
    ],
    eating: [
      "................",
      "......11111.....",
      ".....1222221....",
      "....122242221...",
      "...12242454221..",
      "..1224555554221.",
      "..1225555555521.",
      "..1222555552221.",
      "..1222255522221.",
      "..1222222222221.",
      "...12333333321..",
      "....122333221...",
      ".....1222221....",
      "......13331.....",
      ".....1.....1....",
      "................"
    ],
    sleep: [
      "................",
      "................",
      "................",
      "................",
      "......11111.....",
      ".....1333331....",
      "....133333331...",
      "...13333333331..",
      "..1333333333331.",
      "..1333444433331.",
      "..1333333333331.",
      "...13333333331..",
      "....133333331...",
      ".....1333331....",
      "................",
      "................"
    ],
    sick: [
      "................",
      "......11111.....",
      ".....1222221....",
      "....122222221...",
      "...12242224221..",
      "..1224222422221.",
      "..1222424242221.",
      "..1222222222221.",
      "..1223223223221.",
      "..1222333332221.",
      "...12333333321..",
      "....122333221...",
      ".....1222221....",
      "......13331.....",
      ".....1.....1....",
      "................"
    ],
    dirty: [
      "................",
      "......11111.....",
      ".....1224321....",
      "....142232221...",
      "...12242234221..",
      "..1222424242231.",
      "..1223222222221.",
      "..1222222222221.",
      "..1223233332221.",
      "..1222333333221.",
      "...12333233321..",
      "....122323221...",
      ".....1222321....",
      "......13331.....",
      ".....1.....1....",
      "................"
    ]
  },

  // ── Cube-shaped droid pet ──
  cubo: {
    idle: [
      "................",
      "................",
      "....1111111111..",
      "...122222222211.",
      "...122222222221.",
      "...12244224422.1",
      "...12244224422.1",
      "...12222222222.1",
      "...12222222222.1",
      "...12225555222.1",
      "...12222222222.1",
      "...12222222222.1",
      "...1333333333331",
      "....3.3......3.3",
      "....333......333",
      "................"
    ],
    happy: [
      "................",
      "....1111111111..",
      "...122222222211.",
      "...122222222221.",
      "...12244224422.1",
      "...12244224422.1",
      "...12222222222.1",
      "...12255225522.1",
      "...12255555522.1",
      "...12222552222.1",
      "...12222222222.1",
      "...12222222222.1",
      "...1333333333331",
      "....3.3......3.3",
      "....333......333",
      "................"
    ],
    eating: [
      "................",
      "....1111111111..",
      "...122222222211.",
      "...122222222221.",
      "...12242224422.1",
      "...12242245522.1",
      "...12222255222.1",
      "...12222255222.1",
      "...12222222222.1",
      "...12222222222.1",
      "...12222222222.1",
      "...12222222222.1",
      "...1333333333331",
      "....3.3......3.3",
      "....333......333",
      "................"
    ],
    sleep: [
      "................",
      "................",
      "....1111111111..",
      "...133333333311.",
      "...133333333331.",
      "...13333333333.1",
      "...13333333333.1",
      "...13344333443.1",
      "...13344333443.1",
      "...13333333333.1",
      "...13333333333.1",
      "...13333333333.1",
      "...1333333333331",
      "....3.3......3.3",
      "....333......333",
      "................"
    ],
    sick: [
      "................",
      "....1111111111..",
      "...122232223211.",
      "...122223232221.",
      "...12242224432.1",
      "...12242224432.1",
      "...12232222322.1",
      "...12223222232.1",
      "...12225525222.1",
      "...12222222322.1",
      "...12232223222.1",
      "...12222222222.1",
      "...1333333333331",
      "....3.3......3.3",
      "....333......333",
      "................"
    ],
    dirty: [
      "................",
      "....1111111111..",
      "...122323232211.",
      "...123222322221.",
      "...12244224422.1",
      "...12244224422.1",
      "...12232323232.1",
      "...12223222322.1",
      "...12232332322.1",
      "...12223232232.1",
      "...12232323232.1",
      "...12222322232.1",
      "...1333333333331",
      "....3.3......3.3",
      "....333......333",
      "................"
    ]
  },

  // ── Bird-like hover creature ──
  byte: {
    idle: [
      "................",
      "......11111.....",
      ".....1222221....",
      "....122222221...",
      "...12244244221..",
      "...12244244221..",
      "..12222222222.1.",
      "..12222222222.1.",
      "..1.1222222.1.1.",
      "...112222221....",
      "....12222221....",
      ".....122221.....",
      "......1551......",
      "......1.1.......",
      "......1.1.......",
      "................"
    ],
    happy: [
      "................",
      "......11111.....",
      ".....1222221....",
      "....122222221...",
      "...12242242221..",
      "...12242242221..",
      "..1222222222221.",
      "..1.22522522.21.",
      "..1..2555552..1.",
      "....112222211...",
      "....12222221....",
      ".....122221.....",
      "......1551......",
      "......1.1.......",
      "......1.1.......",
      "................"
    ],
    eating: [
      "................",
      "......11111.....",
      ".....1222221....",
      "....122242221...",
      "...12242452221..",
      "...12245552221..",
      "..12225555222.1.",
      "..12255555522.1.",
      "..1.1255521.1.1.",
      "...112222221....",
      "....12222221....",
      ".....122221.....",
      "......1551......",
      "......1.1.......",
      "......1.1.......",
      "................"
    ],
    sleep: [
      "................",
      "................",
      "......11111.....",
      ".....1333331....",
      "....133333331...",
      "...13344344331..",
      "...13344344331..",
      "..1333333333331.",
      "..1333333333331.",
      "...133333333....",
      "....13333331....",
      ".....133331.....",
      "......1331......",
      "......1.1.......",
      "......1.1.......",
      "................"
    ],
    sick: [
      "................",
      "......11111.....",
      ".....1223221....",
      "....123222231...",
      "...12232322221..",
      "...12242242231..",
      "..12223232222.1.",
      "..12222322222.1.",
      "..1.1222322.1.1.",
      "...112222221....",
      "....12232221....",
      ".....122321.....",
      "......1551......",
      "......1.1.......",
      "......1.1.......",
      "................"
    ],
    dirty: [
      "................",
      "......11111.....",
      ".....1232321....",
      "....132222231...",
      "...12244244231..",
      "...12244244221..",
      "..12323232322.1.",
      "..12232322232.1.",
      "..1.1232323.1.1.",
      "...112223231....",
      "....12223221....",
      ".....123221.....",
      "......1551......",
      "......1.1.......",
      "......1.1.......",
      "................"
    ]
  },

  // ── Skull-ghost experimental creature ──
  spook: {
    idle: [
      "................",
      ".....11111......",
      "....1222221.....",
      "...122222221....",
      "..12222222221...",
      "..12244224421...",
      "..12244224421...",
      "..1224422442.1..",
      "..12222222221...",
      "..12225522221...",
      "..12222222221...",
      "..12222222221...",
      "..121212121211..",
      "..1.1.1.1.1.1...",
      "................",
      "................"
    ],
    happy: [
      "................",
      ".....11111......",
      "....1222221.....",
      "...122222221....",
      "..12222222221...",
      "..12244224421...",
      "..12244224421...",
      "..12255555521...",
      "..12522222251...",
      "..12555555521...",
      "..12222222221...",
      "..12222222221...",
      "..121212121211..",
      "..1.1.1.1.1.1...",
      "................",
      "................"
    ],
    eating: [
      "................",
      ".....11111......",
      "....1222221.....",
      "...122222221....",
      "..12222222221...",
      "..12244224421...",
      "..12242424421...",
      "..12225555221...",
      "..12255555521...",
      "..12225555221...",
      "..12225552221...",
      "..12222222221...",
      "..121212121211..",
      "..1.1.1.1.1.1...",
      "................",
      "................"
    ],
    sleep: [
      "................",
      "................",
      ".....11111......",
      "....1333331.....",
      "...133333331....",
      "..13333333331...",
      "..13344334431...",
      "..13344334431...",
      "..13333333331...",
      "..13333333331...",
      "..13333333331...",
      "..131313131311..",
      "..1.1.1.1.1.1...",
      "................",
      "................",
      "................"
    ],
    sick: [
      "................",
      ".....11111......",
      "....1223221.....",
      "...122322221....",
      "..12322223221...",
      "..12242244221...",
      "..12244244221...",
      "..12232322221...",
      "..12223222321...",
      "..12232332221...",
      "..12222322221...",
      "..12223222221...",
      "..121212121211..",
      "..1.1.1.1.1.1...",
      "................",
      "................"
    ],
    dirty: [
      "................",
      ".....11111......",
      "....1232321.....",
      "...123222231....",
      "..12322323221...",
      "..12244224421...",
      "..12244244321...",
      "..12223232221...",
      "..12322223221...",
      "..12223232321...",
      "..12322323221...",
      "..12223232221...",
      "..121212121211..",
      "..1.1.1.1.1.1...",
      "................",
      "................"
    ]
  }
};

/* resolve CSS var -> rgb */
function getVar(name) {
  return getComputedStyle(document.body).getPropertyValue(name).trim() || "#39ff88";
}

/* build palette from body's active phosphor scheme.
   tokens:
   1 = outline (dim)
   2 = body (bright)
   3 = shade (faint)
   4 = eye (bg-0 hole — near-black)
   5 = accent (white-ish / hot)
*/
function activePalette() {
  return {
    1: getVar('--fg-dim'),
    2: getVar('--fg'),
    3: getVar('--fg-faint'),
    4: getVar('--bg-0'),
    5: getVar('--accent') || getVar('--fg')
  };
}

/* draw sprite matrix onto ctx at given pixel scale, with bounce offset */
function drawSprite(ctx, frame, px, ox = 0, oy = 0) {
  const palette = activePalette();
  for (let y = 0; y < frame.length; y++) {
    const row = frame[y];
    for (let x = 0; x < row.length; x++) {
      const ch = row[x];
      if (ch === '.' || ch === ' ') continue;
      const color = palette[ch];
      if (!color) continue;
      ctx.fillStyle = color;
      ctx.fillRect(ox + x * px, oy + y * px, px, px);
    }
  }
}

/* additional FX */
function drawZzz(ctx, px, baseX, baseY, t) {
  const palette = activePalette();
  ctx.fillStyle = palette[2];
  const glyphs = ['Z','z','z'];
  glyphs.forEach((g, i) => {
    const drift = Math.sin((t / 400) + i) * 4;
    const size = 14 - i * 3;
    ctx.font = `${size}px VT323, monospace`;
    ctx.fillText(g, baseX + i * 10 + drift, baseY - i * 12 - ((t / 80) % 60));
  });
}

function drawHearts(ctx, t, cx, cy) {
  const palette = activePalette();
  ctx.fillStyle = palette[5] || palette[2];
  for (let i = 0; i < 3; i++) {
    const phase = (t / 600 + i * 0.6) % 1;
    const x = cx + Math.sin(phase * Math.PI * 2 + i) * 40;
    const y = cy - phase * 70;
    const a = 1 - phase;
    ctx.globalAlpha = a;
    ctx.font = '14px VT323, monospace';
    ctx.fillText('♥', x, y);
  }
  ctx.globalAlpha = 1;
}

function drawStinkLines(ctx, t, cx, cy) {
  const palette = activePalette();
  ctx.strokeStyle = palette[3];
  ctx.lineWidth = 1;
  for (let i = 0; i < 3; i++) {
    const ox = (i - 1) * 10;
    ctx.beginPath();
    const wob = Math.sin(t / 200 + i) * 3;
    ctx.moveTo(cx + ox, cy);
    ctx.bezierCurveTo(
      cx + ox + 4 + wob, cy - 8,
      cx + ox - 4 - wob, cy - 16,
      cx + ox, cy - 24
    );
    ctx.stroke();
  }
}

/* Main pet renderer component: a canvas that loops and draws the active
   sprite according to state. Exported via window. */

function PetCanvas({ character, state, activity, onReady }) {
  const canvasRef = React.useRef(null);
  const rafRef = React.useRef(0);
  const startRef = React.useRef(performance.now());

  React.useEffect(() => {
    const c = canvasRef.current;
    if (!c) return;
    const ctx = c.getContext('2d');
    ctx.imageSmoothingEnabled = false;

    const loop = (now) => {
      const t = now - startRef.current;
      const w = c.width, h = c.height;
      ctx.clearRect(0, 0, w, h);

      // pick frame based on state / activity
      const char = CHARS[character] || CHARS.blobby;
      let key = 'idle';
      if (state === 'sleeping') key = 'sleep';
      else if (state === 'sick') key = 'sick';
      else if (state === 'dirty') key = 'dirty';
      else if (activity === 'eating') key = 'eating';
      else if (activity === 'playing' || activity === 'happy') key = 'happy';
      const frame = char[key] || char.idle;

      // bounce
      const px = Math.floor(Math.min(w, h) / (SPRITE_SIZE + 2));
      const spriteW = SPRITE_SIZE * px;
      const baseX = Math.floor((w - spriteW) / 2);
      const baseY = Math.floor((h - spriteW) / 2);

      let bounce = 0;
      if (state === 'sleeping') bounce = Math.sin(t / 800) * 1;
      else if (activity === 'playing') bounce = Math.abs(Math.sin(t / 180)) * -10;
      else if (activity === 'eating')  bounce = Math.sin(t / 140) * 2;
      else if (state === 'sick')       bounce = Math.sin(t / 500) * 1.5;
      else                             bounce = Math.sin(t / 400) * 2;

      drawSprite(ctx, frame, px, baseX, baseY + bounce);

      // fx
      if (state === 'sleeping') {
        drawZzz(ctx, px, baseX + spriteW - 4, baseY + 12, t);
      }
      if (activity === 'playing' || activity === 'happy') {
        drawHearts(ctx, t, w / 2, h / 2 - 10);
      }
      if (state === 'dirty') {
        drawStinkLines(ctx, t, w / 2 - 16, baseY + 6);
        drawStinkLines(ctx, t, w / 2 + 16, baseY + 6);
      }
      if (state === 'sick') {
        // red cross marker
        const palette = activePalette();
        ctx.fillStyle = '#ff4e6a';
        ctx.fillRect(baseX + spriteW + 6, baseY + 6, 2, 10);
        ctx.fillRect(baseX + spriteW + 2, baseY + 10, 10, 2);
      }

      rafRef.current = requestAnimationFrame(loop);
    };
    rafRef.current = requestAnimationFrame(loop);
    if (onReady) onReady();

    return () => cancelAnimationFrame(rafRef.current);
  }, [character, state, activity]);

  return React.createElement('canvas', {
    ref: canvasRef,
    width: 280,
    height: 200,
    className: 'pet-canvas'
  });
}

window.PetCanvas = PetCanvas;
window.CHARS = CHARS;
