/* global React */
// Pixel character — Stardew Valley inspired adventurer.
// Green cloak, brown tunic, wooden shield, dark hair.
// Drawn on a 24×32 grid for finer detail than before.

const Palette = {
  skin:      '#e8b88a',
  skinShade: '#c8986a',
  skinDark:  '#a67a50',
  hair:      '#2a1a10',
  hairHi:    '#3e2a1c',
  cloak:     '#4a7a3a',
  cloakHi:   '#5f9050',
  cloakSh:   '#2e4e24',
  tunic:     '#8a5a38',
  tunicHi:   '#a67348',
  tunicSh:   '#5a3a22',
  belt:      '#3a2412',
  pants:     '#5a3a22',
  boots:     '#2e1a0e',
  shieldW:   '#8a5a30',
  shieldW2:  '#6a4220',
  shieldB:   '#d4a74a',   // boss/rim
  shieldB2:  '#a67830',
  eye:       '#1a0e06',
  mouth:     '#6b3c2e',
  blush:     '#e8a080',
  outline:   '#1a0e06',
  // ground mound
  grassTop:  '#6a9040',
  grassTop2: '#4e7230',
  earth:     '#6a4224',
  earthDk:   '#4a2c14',
  earthLt:   '#8a5a32',
  // shine
  white:     '#fff8e8',
};

// Render helper — cells to SVG string
function paintSVG(cells, w, h, extra = '') {
  return `
    <svg viewBox="0 0 ${w} ${h}" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" shape-rendering="crispEdges" preserveAspectRatio="xMidYMid meet" style="image-rendering:pixelated; ${extra}">
      ${cells.map(c => `<rect x="${c.x}" y="${c.y}" width="${c.w || 1}" height="${c.h || 1}" fill="${c.c}"/>`).join('')}
    </svg>
  `;
}

// ------------------------------------------------------------
// FULL BODY ADVENTURER — 24×32 (Stardew-ish)
// Used for Home hero + About portrait (no mound needed there)
// ------------------------------------------------------------
function adventurerCells({ withMound = true, legPhase = 0 } = {}) {
  const P = Palette;
  const c = [];
  const add = (x, y, col, w = 1, h = 1) => c.push({ x, y, w, h, c: col });

  // HAIR BACK
  add(8, 2, P.hair, 8, 1);
  add(7, 3, P.hair, 10, 1);
  add(6, 4, P.hair, 12, 1);
  add(6, 5, P.hair, 12, 1);
  add(6, 6, P.hair, 1, 2);
  add(17, 6, P.hair, 1, 2);

  // HAIR HIGHLIGHT
  add(8, 3, P.hairHi, 2, 1);
  add(12, 3, P.hairHi, 3, 1);
  add(7, 4, P.hairHi, 1, 1);
  add(11, 4, P.hairHi, 2, 1);

  // FACE
  add(7, 6, P.skin, 10, 5);
  // hair over forehead
  add(7, 6, P.hair, 3, 1);
  add(11, 6, P.hair, 1, 1);
  add(13, 6, P.hair, 2, 1);
  add(16, 6, P.hair, 1, 1);
  // ear shade
  add(7, 8, P.skinShade, 1, 1);
  add(16, 8, P.skinShade, 1, 1);
  // eyebrows
  add(9, 7, P.hair, 2, 1);
  add(13, 7, P.hair, 2, 1);
  // eyes
  add(9, 8, P.eye, 2, 1);
  add(13, 8, P.eye, 2, 1);
  // nose shade
  add(11, 9, P.skinShade, 1, 1);
  add(12, 9, P.skinShade, 1, 1);
  // blush
  add(8, 9, P.blush, 1, 1);
  add(15, 9, P.blush, 1, 1);
  // mouth
  add(11, 10, P.mouth, 2, 1);
  // chin shade
  add(8, 10, P.skinShade, 1, 1);
  add(15, 10, P.skinShade, 1, 1);

  // NECK
  add(10, 11, P.skinShade, 4, 1);

  // CLOAK (back drape) — appears behind shoulders, extending to sides/behind
  // left side flap
  add(5, 12, P.cloak, 3, 8);
  add(5, 12, P.cloakHi, 3, 1);
  add(5, 19, P.cloakSh, 3, 1);
  // cloak back behind body on right shoulder
  add(14, 11, P.cloak, 4, 2);
  add(14, 11, P.cloakHi, 4, 1);
  add(17, 13, P.cloak, 1, 6);
  add(17, 13, P.cloakSh, 1, 6);
  // left shoulder cloak
  add(6, 12, P.cloak, 3, 1);
  add(6, 12, P.cloakHi, 3, 1);

  // TUNIC (brown body)
  add(8, 12, P.tunic, 6, 7);
  add(8, 12, P.tunicHi, 6, 1); // collar highlight
  // v-neck
  add(10, 12, P.skin, 2, 1);
  add(10, 13, P.skinShade, 2, 1);
  // tunic shading
  add(13, 13, P.tunicSh, 1, 5);
  add(8, 18, P.tunicSh, 6, 1);
  // belt
  add(8, 17, P.belt, 6, 1);
  // belt buckle
  add(10, 17, P.shieldB, 2, 1);

  // ARMS
  // left arm (holding cloak / hanging) — skin showing (rolled sleeves)
  add(7, 13, P.tunic, 1, 3);
  add(7, 13, P.tunicHi, 1, 1);
  add(7, 16, P.skin, 1, 2);    // forearm
  add(7, 18, P.skin, 1, 1);    // hand
  // right arm tucked behind shield
  add(14, 13, P.tunic, 1, 3);
  add(14, 13, P.tunicHi, 1, 1);

  // SHIELD — round wooden shield on right hand
  // outer rim
  add(15, 13, P.shieldB2, 5, 1);
  add(15, 18, P.shieldB2, 5, 1);
  add(14, 14, P.shieldB2, 1, 4);
  add(20, 14, P.shieldB2, 1, 4);
  // inner wood
  add(15, 14, P.shieldW, 5, 4);
  add(15, 14, P.shieldW, 5, 1);
  add(16, 14, P.shieldW2, 3, 1);
  add(15, 17, P.shieldW2, 5, 1);
  // boss
  add(17, 15, P.shieldB, 1, 2);
  add(17, 15, P.white, 1, 1);
  // wood grain
  add(16, 16, P.shieldW2, 1, 1);
  add(18, 16, P.shieldW2, 1, 1);

  // PANTS
  add(8, 19, P.pants, 6, 3);
  add(8, 19, P.tunicSh, 6, 1); // tunic hem shadow over pants
  add(10, 19, P.belt, 2, 1);   // crotch stitch

  // LEGS — walk phases
  if (legPhase === 0) {
    add(8,  22, P.pants, 2, 2);
    add(12, 22, P.pants, 2, 2);
    add(8,  24, P.boots, 2, 1);
    add(12, 24, P.boots, 2, 1);
  } else if (legPhase === 1) {
    add(9, 22, P.pants, 2, 2);
    add(12, 22, P.pants, 2, 2);
    add(9, 24, P.boots, 3, 1);
    add(12, 24, P.boots, 2, 1);
  } else if (legPhase === 2) {
    add(8, 22, P.pants, 2, 2);
    add(11, 22, P.pants, 2, 2);
    add(8, 24, P.boots, 2, 1);
    add(10, 24, P.boots, 3, 1);
  } else { // jump — both legs tucked up
    add(8,  21, P.pants, 2, 2);
    add(12, 21, P.pants, 2, 2);
    add(8,  23, P.boots, 2, 1);
    add(12, 23, P.boots, 2, 1);
  }

  // GRASS + EARTH MOUND (for big portrait)
  if (withMound) {
    // earth
    add(5, 26, P.earth, 13, 1);
    add(4, 27, P.earth, 15, 2);
    add(5, 29, P.earth, 13, 1);
    add(7, 30, P.earth, 9, 1);
    // earth dark
    add(4, 28, P.earthDk, 15, 1);
    add(5, 29, P.earthDk, 1, 1);
    add(17, 29, P.earthDk, 1, 1);
    add(9, 30, P.earthDk, 1, 1);
    add(14, 30, P.earthDk, 1, 1);
    // earth light
    add(6, 27, P.earthLt, 2, 1);
    add(13, 27, P.earthLt, 3, 1);
    // grass tufts on top
    add(5, 25, P.grassTop, 13, 1);
    add(4, 26, P.grassTop, 1, 1);
    add(18, 26, P.grassTop, 1, 1);
    add(7, 25, P.grassTop2, 2, 1);
    add(11, 25, P.grassTop2, 2, 1);
    add(15, 25, P.grassTop2, 2, 1);
  }

  return c;
}

// 16-wide "tiny walker" used in the footer (smaller pixels than before —
// we render at smaller size so each pixel is ~3-4 screen px instead of 8)
function walkerCells(phase) {
  const cells = adventurerCells({ withMound: false, legPhase: phase });
  return cells;
}

// ------------------------------------------------------------
// Wire walking character frames for #character
// ------------------------------------------------------------
window.addEventListener('DOMContentLoaded', () => {
  const w = 24, h = 26; // crop above mound
  const walk_a = paintSVG(walkerCells(0), w, h);
  const walk_b = paintSVG(walkerCells(1), w, h);
  const walk_c = paintSVG(walkerCells(2), w, h);
  const jump   = paintSVG(walkerCells(3), w, h);
  if (window.setCharacterFrames) {
    window.setCharacterFrames({
      walk_a, walk_b: walk_c, idle: walk_a, jump
    });
  }
});

// ------------------------------------------------------------
// React exports
// ------------------------------------------------------------
function PortraitBig({ size = 320, style = {}, withMound = true }) {
  const h = withMound ? 32 : 26;
  const html = paintSVG(adventurerCells({ withMound, legPhase: 0 }), 24, h);
  return (
    <div style={{ width: size, height: size * (h / 24), imageRendering: 'pixelated', ...style }}
      dangerouslySetInnerHTML={{ __html: html }} />
  );
}

// Animated hero character (idle breathe + occasional wave + click to jump)
function HeroCharacter({ size = 360 }) {
  const [phase, setPhase] = React.useState(0);
  const [jumping, setJumping] = React.useState(false);
  const ref = React.useRef(null);

  React.useEffect(() => {
    let t = 0;
    const id = setInterval(() => {
      t++;
      if (jumping) return;
      if (t % 14 === 0) setPhase(1);
      else if (t % 14 === 1) setPhase(2);
      else setPhase(0);
    }, 280);
    return () => clearInterval(id);
  }, [jumping]);

  const h = 32;
  const html = paintSVG(adventurerCells({ withMound: true, legPhase: jumping ? 3 : phase }), 24, h);

  const onClick = () => {
    if (jumping) return;
    setJumping(true);
    if (window.__triggerHeroDust && ref.current) window.__triggerHeroDust(ref.current);
    setTimeout(() => setJumping(false), 520);
  };

  return (
    <div
      ref={ref}
      onClick={onClick}
      style={{
        width: size, height: size * (h / 24),
        imageRendering: 'pixelated',
        cursor: 'none',
        animation: jumping
          ? 'heroJump 520ms steps(8, end)'
          : 'heroFloat 3.2s ease-in-out infinite',
      }}
      dangerouslySetInnerHTML={{ __html: html }}
    />
  );
}

function CharMini({ size = 64 }) {
  const html = paintSVG(walkerCells(0), 24, 26);
  return (
    <div style={{ width: size, height: size * (26/24) }}
      dangerouslySetInnerHTML={{ __html: html }} />
  );
}

// Pixel section icons (1-bit, 12x12) — kept small & crisp
function PxIcon({ type, color = 'currentColor', size = 14 }) {
  const I = {
    home: [[6,1],[5,2],[6,2],[7,2],[4,3],[5,3],[6,3],[7,3],[8,3],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[9,4],[2,5],[3,5],[4,5],[5,5],[6,5],[7,5],[8,5],[9,5],[10,5],[3,6],[9,6],[3,7],[9,7],[5,7],[6,7],[7,7],[3,8],[9,8],[5,8],[6,8],[7,8],[3,9],[4,9],[5,9],[6,9],[7,9],[8,9],[9,9]],
    user: [[4,2],[5,2],[6,2],[7,2],[3,3],[4,3],[5,3],[6,3],[7,3],[8,3],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[4,5],[5,5],[6,5],[7,5],[2,7],[3,7],[4,7],[5,7],[6,7],[7,7],[8,7],[9,7],[1,8],[2,8],[9,8],[10,8],[1,9],[10,9],[1,10],[2,10],[3,10],[4,10],[5,10],[6,10],[7,10],[8,10],[9,10],[10,10]],
    mail: [[1,3],[2,3],[3,3],[4,3],[5,3],[6,3],[7,3],[8,3],[9,3],[10,3],[1,4],[10,4],[2,4],[9,4],[3,5],[8,5],[4,6],[7,6],[5,7],[6,7],[1,8],[10,8],[1,9],[10,9],[1,10],[2,10],[3,10],[4,10],[5,10],[6,10],[7,10],[8,10],[9,10],[10,10]],
    exp: [[4,2],[5,2],[6,2],[7,2],[4,3],[7,3],[1,4],[2,4],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[9,4],[10,4],[1,5],[10,5],[5,5],[6,5],[1,6],[10,6],[5,6],[6,6],[1,7],[10,7],[1,8],[10,8],[1,9],[2,9],[3,9],[4,9],[5,9],[6,9],[7,9],[8,9],[9,9],[10,9]],
    proj: [[1,3],[2,3],[3,3],[4,3],[5,3],[1,4],[5,4],[6,4],[7,4],[8,4],[9,4],[10,4],[1,5],[10,5],[1,6],[10,6],[1,7],[10,7],[1,8],[10,8],[1,9],[2,9],[3,9],[4,9],[5,9],[6,9],[7,9],[8,9],[9,9],[10,9]],
    cert: [[4,1],[5,1],[6,1],[7,1],[3,2],[8,2],[3,3],[8,3],[3,4],[8,4],[4,5],[5,5],[6,5],[7,5],[5,6],[6,6],[4,7],[7,7],[3,8],[8,8],[4,9],[7,9],[5,10],[6,10]],
    skill: [[5,1],[6,1],[4,2],[7,2],[3,3],[8,3],[2,4],[9,4],[1,5],[10,5],[2,6],[9,6],[3,7],[8,7],[4,8],[7,8],[5,9],[6,9]],
    book: [[2,2],[3,2],[4,2],[5,2],[6,2],[7,2],[8,2],[9,2],[2,3],[9,3],[2,4],[9,4],[4,4],[5,4],[6,4],[7,4],[2,5],[9,5],[2,6],[9,6],[4,6],[5,6],[6,6],[7,6],[2,7],[9,7],[2,8],[9,8],[2,9],[3,9],[4,9],[5,9],[6,9],[7,9],[8,9],[9,9]],
  };
  const pts = I[type] || I.home;
  return (
    <svg viewBox="0 0 12 12" width={size} height={size} shapeRendering="crispEdges"
         style={{imageRendering:'pixelated', display:'inline-block', verticalAlign:'middle'}}>
      {pts.map((p, i) => <rect key={i} x={p[0]} y={p[1]} width="1" height="1" fill={color} />)}
    </svg>
  );
}

function TechBadge({ tech, size = 22 }) {
  const map = {
    react: { bg:'#0a2530', fg:'#22d3ee', cells:[[6,6],[7,6],[5,7],[8,7],[4,8],[9,8],[4,9],[9,9],[5,10],[8,10],[6,11],[7,11],[6,8],[7,8],[6,9],[7,9]]},
    node:  { bg:'#0a2015', fg:'#86efac', cells:[[6,3],[7,3],[5,4],[8,4],[4,5],[9,5],[3,6],[10,6],[3,7],[10,7],[3,8],[10,8],[3,9],[10,9],[4,10],[9,10],[5,11],[8,11],[6,12],[7,12]]},
    ts:    { bg:'#1d3a6f', fg:'#e6e6ff', cells:[[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[9,4],[10,4],[6,5],[7,5],[6,6],[7,6],[6,7],[7,7],[6,8],[7,8],[6,9],[7,9],[6,10],[7,10]]},
    py:    { bg:'#1a3a5c', fg:'#fde047', cells:[[5,3],[6,3],[7,3],[8,3],[4,4],[9,4],[4,5],[9,5],[3,6],[4,6],[5,6],[6,6],[7,6],[8,6],[9,6],[10,6],[3,7],[10,7],[5,8],[6,8],[7,8],[8,8],[9,8],[10,8],[3,9],[4,9],[5,9],[6,9],[7,9],[8,9],[10,9],[3,10],[10,10],[4,11],[9,11],[5,12],[6,12],[7,12],[8,12]]},
    go:    { bg:'#0a2530', fg:'#22d3ee', cells:[[3,6],[4,6],[5,6],[6,6],[7,6],[8,6],[9,6],[10,6],[3,7],[10,7],[3,8],[10,8],[3,9],[10,9],[5,10],[6,10],[7,10],[8,10]]},
    aws:   { bg:'#2a1a05', fg:'#fb923c', cells:[[2,5],[3,5],[4,5],[5,5],[8,5],[9,5],[10,5],[11,5],[3,6],[4,6],[9,6],[10,6],[2,8],[3,8],[10,8],[11,8],[2,9],[3,9],[4,9],[5,9],[6,9],[7,9],[8,9],[9,9],[10,9],[11,9]]},
    docker:{ bg:'#0a2530', fg:'#22d3ee', cells:[[3,8],[4,8],[5,8],[6,8],[7,8],[8,8],[9,8],[10,8],[11,8],[3,7],[4,7],[3,6],[4,6],[5,7],[6,7],[5,6],[6,6],[7,7],[8,7],[7,6],[8,6],[9,7],[10,7],[6,5],[8,5],[2,9],[3,9],[4,9],[5,9],[6,9],[7,9],[8,9],[9,9],[10,9],[11,9]]},
    pg:    { bg:'#0a1530', fg:'#a78bfa', cells:[[4,3],[5,3],[6,3],[7,3],[8,3],[9,3],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[9,4],[10,4],[3,5],[10,5],[3,6],[10,6],[3,7],[10,7],[3,8],[10,8],[4,9],[5,9],[6,9],[7,9],[8,9],[9,9],[10,9],[6,10],[7,10]]},
    git:   { bg:'#2a0a0a', fg:'#f472b6', cells:[[6,2],[7,2],[6,3],[7,3],[6,4],[7,4],[5,5],[8,5],[4,6],[9,6],[3,7],[10,7],[4,8],[9,8],[5,9],[8,9],[6,10],[7,10],[6,11],[7,11]]},
    gql:   { bg:'#2a0a20', fg:'#f472b6', cells:[[6,2],[7,2],[5,3],[8,3],[4,4],[9,4],[3,5],[10,5],[3,6],[10,6],[3,7],[10,7],[3,8],[10,8],[4,9],[9,9],[5,10],[8,10],[6,11],[7,11]]},
    redis: { bg:'#2a0a0a', fg:'#e55', cells:[[3,5],[4,5],[5,5],[6,5],[7,5],[8,5],[9,5],[10,5],[3,6],[10,6],[3,7],[10,7],[3,8],[4,8],[5,8],[6,8],[7,8],[8,8],[9,8],[10,8],[3,10],[4,10],[5,10],[6,10],[7,10],[8,10],[9,10],[10,10]]},
    swift: { bg:'#2a0a05', fg:'#fb923c', cells:[[4,3],[5,3],[6,3],[7,3],[8,3],[9,3],[3,4],[4,4],[9,4],[10,4],[3,5],[10,5],[3,6],[10,6],[4,7],[9,7],[5,8],[8,8],[6,9],[7,9]]},
  };
  const t = map[tech] || map.react;
  return (
    <svg viewBox="0 0 14 14" width={size} height={size} shapeRendering="crispEdges"
         style={{imageRendering:'pixelated'}}>
      <rect width="14" height="14" fill={t.bg}/>
      {t.cells.map((p, i) => <rect key={i} x={p[0]} y={p[1]} width="1" height="1" fill={t.fg}/>)}
    </svg>
  );
}

window.PortraitBig = PortraitBig;
window.HeroCharacter = HeroCharacter;
window.CharMini = CharMini;
window.PxIcon = PxIcon;
window.TechBadge = TechBadge;

// Provide static adventurer SVG for intro.js (vanilla)
window.__drawIntroChar = () => paintSVG(adventurerCells({ withMound: true, legPhase: 0 }), 24, 32);
