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

// ---------- Palettes ----------
const PALETTES = {
  ink: { bg: "#0A0500", fg: "#FF5C6E", alt: "#15D528", name: "ink & ember" },
  forest: { bg: "#022D07", fg: "#FF001F", alt: "#15D528", name: "forest & flare" },
  bone: { bg: "#F2EBDD", fg: "#1A1A1A", alt: "#FF001F", name: "bone & black" },
  bruise: { bg: "#0B0820", fg: "#FF4DA6", alt: "#7A4DFF", name: "bruise & bubblegum" },
};

// ---------- Primitive Stamps ----------
// Each stamp is a function that returns SVG given (cx, cy, size, color, alt)
const STAMPS = {
  dot: (cx, cy, s, c) => (
    <circle cx={cx} cy={cy} r={s * 0.28} fill={c} />
  ),
  block: (cx, cy, s, c) => (
    <rect x={cx - s * 0.4} y={cy - s * 0.4} width={s * 0.8} height={s * 0.8} fill={c} />
  ),
  bar: (cx, cy, s, c) => (
    <rect x={cx - s * 0.45} y={cy - s * 0.18} width={s * 0.9} height={s * 0.36} fill={c} />
  ),
  arch: (cx, cy, s, c) => (
    <path d={`M ${cx - s * 0.4} ${cy + s * 0.2} A ${s * 0.4} ${s * 0.4} 0 0 1 ${cx + s * 0.4} ${cy + s * 0.2} Z`} fill={c} />
  ),
  cup: (cx, cy, s, c) => (
    <path d={`M ${cx - s * 0.4} ${cy - s * 0.2} A ${s * 0.4} ${s * 0.4} 0 0 0 ${cx + s * 0.4} ${cy - s * 0.2} L ${cx + s * 0.4} ${cy - s * 0.2} L ${cx - s * 0.4} ${cy - s * 0.2} Z`} fill={c} transform={`rotate(180 ${cx} ${cy})`} />
  ),
  tri: (cx, cy, s, c) => (
    <path d={`M ${cx} ${cy - s * 0.4} L ${cx + s * 0.4} ${cy + s * 0.3} L ${cx - s * 0.4} ${cy + s * 0.3} Z`} fill={c} />
  ),
  triDown: (cx, cy, s, c) => (
    <path d={`M ${cx} ${cy + s * 0.4} L ${cx + s * 0.4} ${cy - s * 0.3} L ${cx - s * 0.4} ${cy - s * 0.3} Z`} fill={c} />
  ),
  ring: (cx, cy, s, c) => (
    <g>
      <circle cx={cx} cy={cy} r={s * 0.4} fill={c} />
      <circle cx={cx} cy={cy} r={s * 0.18} fill="var(--bg)" />
    </g>
  ),
  cross: (cx, cy, s, c) => (
    <g fill={c}>
      <rect x={cx - s * 0.45} y={cy - s * 0.12} width={s * 0.9} height={s * 0.24} />
      <rect x={cx - s * 0.12} y={cy - s * 0.45} width={s * 0.24} height={s * 0.9} />
    </g>
  ),
  notch: (cx, cy, s, c) => (
    <g fill={c}>
      <rect x={cx - s * 0.4} y={cy - s * 0.4} width={s * 0.4} height={s * 0.4} />
      <rect x={cx} y={cy} width={s * 0.4} height={s * 0.4} />
    </g>
  ),
  half: (cx, cy, s, c) => (
    <path d={`M ${cx - s * 0.4} ${cy} A ${s * 0.4} ${s * 0.4} 0 0 1 ${cx + s * 0.4} ${cy} Z`} fill={c} />
  ),
};

const STAMP_KEYS = Object.keys(STAMPS);

// ---------- Preset creatures ----------
// 6x6 grids — each cell is { stamp, color: 'fg'|'alt' } or null
const blank = () => Array.from({ length: 6 }, () => Array(6).fill(null));

const PRESETS = {
  doc: (() => {
    const g = blank();
    // doc: a tall figure with a cup (hat) and dot eyes
    g[0][2] = { stamp: "cup", color: "fg" };
    g[0][3] = { stamp: "cup", color: "fg" };
    g[1][1] = { stamp: "arch", color: "fg" };
    g[1][2] = { stamp: "block", color: "fg" };
    g[1][3] = { stamp: "block", color: "fg" };
    g[1][4] = { stamp: "arch", color: "fg" };
    g[2][2] = { stamp: "dot", color: "alt" };
    g[2][3] = { stamp: "dot", color: "alt" };
    g[3][1] = { stamp: "block", color: "fg" };
    g[3][2] = { stamp: "bar", color: "fg" };
    g[3][3] = { stamp: "bar", color: "fg" };
    g[3][4] = { stamp: "block", color: "fg" };
    g[4][2] = { stamp: "block", color: "fg" };
    g[4][3] = { stamp: "block", color: "fg" };
    g[5][1] = { stamp: "half", color: "fg" };
    g[5][4] = { stamp: "half", color: "fg" };
    return g;
  })(),
  duck: (() => {
    const g = blank();
    // duck: a squat round body, beak triangle
    g[1][3] = { stamp: "arch", color: "alt" };
    g[1][4] = { stamp: "block", color: "alt" };
    g[2][2] = { stamp: "tri", color: "fg" };
    g[2][3] = { stamp: "ring", color: "alt" };
    g[2][4] = { stamp: "arch", color: "alt" };
    g[3][1] = { stamp: "half", color: "alt" };
    g[3][2] = { stamp: "block", color: "alt" };
    g[3][3] = { stamp: "block", color: "alt" };
    g[3][4] = { stamp: "block", color: "alt" };
    g[4][1] = { stamp: "cup", color: "alt" };
    g[4][2] = { stamp: "cup", color: "alt" };
    g[4][3] = { stamp: "cup", color: "alt" };
    g[4][4] = { stamp: "cup", color: "alt" };
    g[5][2] = { stamp: "tri", color: "fg" };
    g[5][3] = { stamp: "tri", color: "fg" };
    return g;
  })(),
  totem: (() => {
    const g = blank();
    g[0][2] = { stamp: "tri", color: "fg" };
    g[0][3] = { stamp: "tri", color: "fg" };
    g[1][2] = { stamp: "ring", color: "fg" };
    g[1][3] = { stamp: "ring", color: "fg" };
    g[2][1] = { stamp: "bar", color: "fg" };
    g[2][2] = { stamp: "cross", color: "alt" };
    g[2][3] = { stamp: "cross", color: "alt" };
    g[2][4] = { stamp: "bar", color: "fg" };
    g[3][2] = { stamp: "block", color: "fg" };
    g[3][3] = { stamp: "block", color: "fg" };
    g[4][1] = { stamp: "half", color: "alt" };
    g[4][2] = { stamp: "notch", color: "fg" };
    g[4][3] = { stamp: "notch", color: "fg" };
    g[4][4] = { stamp: "half", color: "alt" };
    g[5][2] = { stamp: "arch", color: "fg" };
    g[5][3] = { stamp: "arch", color: "fg" };
    return g;
  })(),
  bug: (() => {
    const g = blank();
    g[1][1] = { stamp: "dot", color: "fg" };
    g[1][4] = { stamp: "dot", color: "fg" };
    g[2][1] = { stamp: "half", color: "alt" };
    g[2][2] = { stamp: "ring", color: "fg" };
    g[2][3] = { stamp: "ring", color: "fg" };
    g[2][4] = { stamp: "half", color: "alt" };
    g[3][2] = { stamp: "block", color: "alt" };
    g[3][3] = { stamp: "block", color: "alt" };
    g[4][1] = { stamp: "tri", color: "fg" };
    g[4][2] = { stamp: "cup", color: "alt" };
    g[4][3] = { stamp: "cup", color: "alt" };
    g[4][4] = { stamp: "tri", color: "fg" };
    g[5][2] = { stamp: "dot", color: "fg" };
    g[5][3] = { stamp: "dot", color: "fg" };
    return g;
  })(),
};

// ---------- Renderer for a 6x6 grid ----------
function CreatureSVG({ grid, size = 360, palette, animated = false, t = 0 }) {
  const cell = size / 6;
  return (
    <svg viewBox={`0 0 ${size} ${size}`} width="100%" height="100%" style={{ display: "block" }}>
      <rect width={size} height={size} fill={palette.bg} />
      {grid.flatMap((row, ry) =>
        row.map((c, cx) => {
          if (!c) return null;
          const color = c.color === "alt" ? palette.alt : palette.fg;
          const px = cx * cell + cell / 2;
          const py = ry * cell + cell / 2;
          const wob = animated ? Math.sin((t + ry * 7 + cx * 11) / 18) * 0.04 : 0;
          const s = cell * (1 + wob);
          return (
            <g key={`${ry}-${cx}`}>
              {STAMPS[c.stamp](px, py, s, color)}
            </g>
          );
        })
      )}
    </svg>
  );
}

// ---------- Stamp swatch icon (for palette) ----------
function StampIcon({ stamp, color, bg }) {
  return (
    <svg viewBox="0 0 40 40" width="40" height="40">
      <rect width="40" height="40" fill={bg} />
      {STAMPS[stamp](20, 20, 40, color)}
    </svg>
  );
}

// ---------- Main App ----------
function App() {
  const [tweaks, setTweak] = useTweaks(/*EDITMODE-BEGIN*/{
    "paletteKey": "forest",
    "creatureName": "doc",
    "showGuides": true,
    "wobble": true
  }/*EDITMODE-END*/);

  const palette = PALETTES[tweaks.paletteKey] || PALETTES.forest;

  const [grid, setGrid] = useState(() => PRESETS.doc.map(r => r.slice()));
  const [activeStamp, setActiveStamp] = useState("block");
  const [activeColor, setActiveColor] = useState("fg");
  const [tool, setTool] = useState("paint"); // paint | erase
  const [history, setHistory] = useState([]);
  const [t, setT] = useState(0);
  const [savedCreatures, setSavedCreatures] = useState([]);
  const [name, setName] = useState("doc");
  const [shake, setShake] = useState(false);

  // animation tick
  useEffect(() => {
    if (!tweaks.wobble) return;
    let raf;
    const tick = () => {
      setT(v => v + 1);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [tweaks.wobble]);

  const pushHistory = (g) => {
    setHistory(h => [...h.slice(-30), g.map(r => r.slice())]);
  };

  const setCell = (r, c) => {
    pushHistory(grid);
    setGrid(g => {
      const ng = g.map(row => row.slice());
      if (tool === "erase") ng[r][c] = null;
      else ng[r][c] = { stamp: activeStamp, color: activeColor };
      return ng;
    });
  };

  const undo = () => {
    setHistory(h => {
      if (!h.length) return h;
      const last = h[h.length - 1];
      setGrid(last);
      return h.slice(0, -1);
    });
  };

  const clear = () => {
    pushHistory(grid);
    setGrid(blank());
  };

  const loadPreset = (key) => {
    pushHistory(grid);
    setGrid(PRESETS[key].map(r => r.slice()));
    setName(key);
    setTweak("creatureName", key);
  };

  const randomize = () => {
    pushHistory(grid);
    const ng = blank();
    const fillCount = 12 + Math.floor(Math.random() * 14);
    for (let i = 0; i < fillCount; i++) {
      const r = Math.floor(Math.random() * 6);
      const c = Math.floor(Math.random() * 6);
      // mirror for symmetry
      const stamp = STAMP_KEYS[Math.floor(Math.random() * STAMP_KEYS.length)];
      const color = Math.random() < 0.7 ? "fg" : "alt";
      ng[r][c] = { stamp, color };
      ng[r][5 - c] = { stamp, color };
    }
    setGrid(ng);
    setShake(true);
    setTimeout(() => setShake(false), 400);
  };

  const save = () => {
    if (!grid.flat().some(Boolean)) return;
    setSavedCreatures(s => [{ id: Date.now(), grid: grid.map(r => r.slice()), name: name || "untitled" }, ...s].slice(0, 12));
  };

  const deleteSaved = (id) => {
    setSavedCreatures(s => s.filter(x => x.id !== id));
  };

  const exportSVG = () => {
    const size = 600;
    const cell = size / 6;
    let inner = `<rect width="${size}" height="${size}" fill="${palette.bg}"/>`;
    grid.forEach((row, ry) => row.forEach((c, cx) => {
      if (!c) return;
      const color = c.color === "alt" ? palette.alt : palette.fg;
      const px = cx * cell + cell / 2;
      const py = ry * cell + cell / 2;
      const s = cell;
      const stamps = {
        dot: `<circle cx="${px}" cy="${py}" r="${s*0.28}" fill="${color}"/>`,
        block: `<rect x="${px-s*0.4}" y="${py-s*0.4}" width="${s*0.8}" height="${s*0.8}" fill="${color}"/>`,
        bar: `<rect x="${px-s*0.45}" y="${py-s*0.18}" width="${s*0.9}" height="${s*0.36}" fill="${color}"/>`,
        arch: `<path d="M ${px-s*0.4} ${py+s*0.2} A ${s*0.4} ${s*0.4} 0 0 1 ${px+s*0.4} ${py+s*0.2} Z" fill="${color}"/>`,
        cup: `<path d="M ${px-s*0.4} ${py-s*0.2} A ${s*0.4} ${s*0.4} 0 0 0 ${px+s*0.4} ${py-s*0.2} Z" fill="${color}" transform="rotate(180 ${px} ${py})"/>`,
        tri: `<path d="M ${px} ${py-s*0.4} L ${px+s*0.4} ${py+s*0.3} L ${px-s*0.4} ${py+s*0.3} Z" fill="${color}"/>`,
        triDown: `<path d="M ${px} ${py+s*0.4} L ${px+s*0.4} ${py-s*0.3} L ${px-s*0.4} ${py-s*0.3} Z" fill="${color}"/>`,
        ring: `<circle cx="${px}" cy="${py}" r="${s*0.4}" fill="${color}"/><circle cx="${px}" cy="${py}" r="${s*0.18}" fill="${palette.bg}"/>`,
        cross: `<rect x="${px-s*0.45}" y="${py-s*0.12}" width="${s*0.9}" height="${s*0.24}" fill="${color}"/><rect x="${px-s*0.12}" y="${py-s*0.45}" width="${s*0.24}" height="${s*0.9}" fill="${color}"/>`,
        notch: `<rect x="${px-s*0.4}" y="${py-s*0.4}" width="${s*0.4}" height="${s*0.4}" fill="${color}"/><rect x="${px}" y="${py}" width="${s*0.4}" height="${s*0.4}" fill="${color}"/>`,
        half: `<path d="M ${px-s*0.4} ${py} A ${s*0.4} ${s*0.4} 0 0 1 ${px+s*0.4} ${py} Z" fill="${color}"/>`,
      };
      inner += stamps[c.stamp] || "";
    }));
    const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" width="${size}" height="${size}">${inner}</svg>`;
    const blob = new Blob([svg], { type: "image/svg+xml" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `${name || "creature"}.svg`;
    a.click();
    URL.revokeObjectURL(url);
  };

  const cellCount = grid.flat().filter(Boolean).length;

  return (
    <div className="app" style={{ "--bg": palette.bg, "--fg": palette.fg, "--alt": palette.alt }}>
      <header className="topbar">
        <div className="brand">
          <span className="brand-mark">
            <svg viewBox="0 0 24 24" width="22" height="22"><rect x="2" y="2" width="9" height="9" fill={palette.fg}/><rect x="13" y="2" width="9" height="9" fill={palette.fg}/><rect x="2" y="13" width="9" height="9" fill={palette.alt}/><rect x="13" y="13" width="9" height="9" fill={palette.fg}/></svg>
          </span>
          <span className="brand-word">block&nbsp;party</span>
          <span className="brand-tag">a creature studio</span>
        </div>
        <div className="palette-row">
          {Object.entries(PALETTES).map(([k, p]) => (
            <button
              key={k}
              className={`pchip ${tweaks.paletteKey === k ? "on" : ""}`}
              onClick={() => setTweak("paletteKey", k)}
              title={p.name}
            >
              <span style={{ background: p.bg }}/>
              <span style={{ background: p.fg }}/>
              <span style={{ background: p.alt }}/>
            </button>
          ))}
        </div>
      </header>

      <main className="stage">
        <aside className="panel left">
          <div className="panel-title">stamps</div>
          <div className="stamp-grid">
            {STAMP_KEYS.map(k => (
              <button
                key={k}
                className={`stamp ${activeStamp === k ? "on" : ""}`}
                onClick={() => { setActiveStamp(k); setTool("paint"); }}
                title={k}
              >
                <StampIcon stamp={k} color={activeColor === "alt" ? palette.alt : palette.fg} bg={palette.bg}/>
              </button>
            ))}
          </div>

          <div className="panel-title mt">color</div>
          <div className="color-row">
            <button className={`color-chip ${activeColor === "fg" ? "on" : ""}`} onClick={() => setActiveColor("fg")}>
              <span style={{ background: palette.fg }}/>
              <em>main</em>
            </button>
            <button className={`color-chip ${activeColor === "alt" ? "on" : ""}`} onClick={() => setActiveColor("alt")}>
              <span style={{ background: palette.alt }}/>
              <em>alt</em>
            </button>
          </div>

          <div className="panel-title mt">tool</div>
          <div className="tool-row">
            <button className={`tool ${tool === "paint" ? "on" : ""}`} onClick={() => setTool("paint")}>paint</button>
            <button className={`tool ${tool === "erase" ? "on" : ""}`} onClick={() => setTool("erase")}>erase</button>
          </div>
        </aside>

        <section className={`canvas-wrap ${shake ? "shake" : ""}`}>
          <div className="canvas-frame">
            <div className={`grid ${tweaks.showGuides ? "guides" : ""}`}>
              <CreatureSVG grid={grid} palette={palette} animated={tweaks.wobble} t={t} />
              <div className="grid-overlay">
                {Array.from({ length: 36 }).map((_, i) => {
                  const r = Math.floor(i / 6), c = i % 6;
                  return (
                    <button
                      key={i}
                      className="cell"
                      onMouseDown={() => setCell(r, c)}
                      onMouseEnter={(e) => { if (e.buttons === 1) setCell(r, c); }}
                    />
                  );
                })}
              </div>
            </div>
            <div className="caption">
              <input
                value={name}
                onChange={e => setName(e.target.value)}
                className="name-input"
                spellCheck={false}
                maxLength={24}
              />
              <span className="meta">{cellCount} blocks · {palette.name}</span>
            </div>
          </div>

          <div className="actions">
            <button className="btn" onClick={undo} disabled={!history.length}>↶ undo</button>
            <button className="btn" onClick={clear}>clear</button>
            <button className="btn" onClick={randomize}>shake!</button>
            <button className="btn primary" onClick={save}>save creature</button>
            <button className="btn" onClick={exportSVG}>export svg</button>
          </div>
        </section>

        <aside className="panel right">
          <div className="panel-title">presets</div>
          <div className="preset-grid">
            {Object.keys(PRESETS).map(k => (
              <button key={k} className="preset" onClick={() => loadPreset(k)}>
                <div className="preset-thumb">
                  <CreatureSVG grid={PRESETS[k]} palette={palette} />
                </div>
                <span>{k}</span>
              </button>
            ))}
          </div>

          <div className="panel-title mt">menagerie</div>
          {savedCreatures.length === 0 ? (
            <div className="empty">no creatures yet.<br/>build one. hit save.</div>
          ) : (
            <div className="saved-grid">
              {savedCreatures.map(s => (
                <div key={s.id} className="saved">
                  <div className="saved-thumb" onClick={() => { setGrid(s.grid.map(r => r.slice())); setName(s.name); }}>
                    <CreatureSVG grid={s.grid} palette={palette} />
                  </div>
                  <div className="saved-row">
                    <span className="saved-name">{s.name}</span>
                    <button className="x" onClick={() => deleteSaved(s.id)}>×</button>
                  </div>
                </div>
              ))}
            </div>
          )}
        </aside>
      </main>

      <footer className="footbar">
        <span>drag across cells to paint · hold shift on a stamp to flip · this is yours, not mine</span>
        <span className="dot-row"><i/><i/><i/></span>
      </footer>

      <TweaksPanel title="Tweaks">
        <TweakSection title="palette">
          <TweakRadio
            value={tweaks.paletteKey}
            onChange={v => setTweak("paletteKey", v)}
            options={Object.keys(PALETTES).map(k => ({ value: k, label: k }))}
          />
        </TweakSection>
        <TweakSection title="vibes">
          <TweakToggle label="grid guides" value={tweaks.showGuides} onChange={v => setTweak("showGuides", v)} />
          <TweakToggle label="wobble" value={tweaks.wobble} onChange={v => setTweak("wobble", v)} />
        </TweakSection>
        <TweakSection title="quick load">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
            {Object.keys(PRESETS).map(k => (
              <TweakButton key={k} onClick={() => loadPreset(k)}>{k}</TweakButton>
            ))}
          </div>
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
