/* art.jsx — Watercolor blooms, halftone, paper texture, ornaments */
/* global React */

const { useMemo, useId } = React;

/* ============================================================
   <Bloom /> — watercolor stain
   ============================================================ */
function Bloom({ color = "var(--bloom)", size = 360, top = 0, left = 0, opacity = 0.55, seed = 1, style = {} }) {
  const id = useId();
  const intensity = "var(--wc-intensity, 1)";
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 200 200"
      style={{
        position: "absolute",
        top,
        left,
        pointerEvents: "none",
        opacity: `calc(${opacity} * ${intensity})`,
        mixBlendMode: "multiply",
        ...style,
      }}
      aria-hidden="true"
    >
      <defs>
        <filter id={`wc-${id}`} x="-20%" y="-20%" width="140%" height="140%">
          <feTurbulence type="fractalNoise" baseFrequency="0.018" numOctaves="2" seed={seed} />
          <feDisplacementMap in="SourceGraphic" scale="28" />
          <feGaussianBlur stdDeviation="1.4" />
        </filter>
        <radialGradient id={`gr-${id}`} cx="50%" cy="48%" r="55%">
          <stop offset="0%" stopColor={color} stopOpacity="0.95" />
          <stop offset="55%" stopColor={color} stopOpacity="0.55" />
          <stop offset="100%" stopColor={color} stopOpacity="0" />
        </radialGradient>
        <filter id={`grain-${id}`}>
          <feTurbulence type="fractalNoise" baseFrequency="0.7" numOctaves="2" seed={seed + 7}/>
          <feColorMatrix values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.4 0"/>
          <feComposite in2="SourceGraphic" operator="in"/>
        </filter>
      </defs>
      <g filter={`url(#wc-${id})`}>
        <circle cx="100" cy="100" r="76" fill={`url(#gr-${id})`} />
        <circle cx="92" cy="88" r="36" fill={color} opacity="0.18" />
        <circle cx="118" cy="112" r="22" fill={color} opacity="0.12" />
      </g>
      {/* grain dots */}
      <g opacity="0.5">
        <rect width="200" height="200" fill={color} filter={`url(#grain-${id})`} opacity="0.18" />
      </g>
    </svg>
  );
}

/* ============================================================
   <Splatter /> — ink/watercolor specks
   ============================================================ */
function Splatter({ color = "var(--accent)", size = 200, seed = 2, style = {} }) {
  const id = useId();
  const rng = mulberry(seed);
  const dots = Array.from({ length: 24 }).map((_, i) => ({
    cx: rng() * 200,
    cy: rng() * 200,
    r: 0.5 + rng() * 3.4,
    o: 0.15 + rng() * 0.55,
  }));
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 200 200"
      style={{ position: "absolute", pointerEvents: "none", mixBlendMode: "multiply", ...style }}
      aria-hidden="true"
    >
      <defs>
        <filter id={`sp-${id}`}>
          <feTurbulence type="fractalNoise" baseFrequency="0.05" numOctaves="2" seed={seed} />
          <feDisplacementMap in="SourceGraphic" scale="6" />
        </filter>
      </defs>
      <g filter={`url(#sp-${id})`} fill={color}>
        {dots.map((d, i) => (
          <circle key={i} cx={d.cx} cy={d.cy} r={d.r} opacity={d.o} />
        ))}
      </g>
    </svg>
  );
}

/* mulberry32 PRNG */
function mulberry(a) {
  return function () {
    a |= 0; a = a + 0x6D2B79F5 | 0;
    let t = a;
    t = Math.imul(t ^ t >>> 15, t | 1);
    t ^= t + Math.imul(t ^ t >>> 7, t | 61);
    return ((t ^ t >>> 14) >>> 0) / 4294967296;
  };
}

/* ============================================================
   <Halftone /> — dot pattern square
   ============================================================ */
function Halftone({ color = "var(--ink)", width = 240, height = 140, density = 5, style = {} }) {
  return (
    <div
      style={{
        width,
        height,
        backgroundImage: `radial-gradient(circle, ${color} 1px, transparent 1.6px)`,
        backgroundSize: `${density}px ${density}px`,
        ...style,
      }}
      aria-hidden="true"
    />
  );
}

/* ============================================================
   <RegistrationMark /> — print registration crosshair
   ============================================================ */
function RegistrationMark({ size = 30, color = "var(--ink)", style = {} }) {
  return (
    <svg width={size} height={size} viewBox="0 0 30 30" style={style} aria-hidden="true">
      <circle cx="15" cy="15" r="9" fill="none" stroke={color} strokeWidth="1" />
      <line x1="15" y1="0" x2="15" y2="30" stroke={color} strokeWidth="1" />
      <line x1="0" y1="15" x2="30" y2="15" stroke={color} strokeWidth="1" />
    </svg>
  );
}

/* ============================================================
   <ColorBar /> — CMYK strip. Click any swatch to switch the site's
   accent color. Preference persists in localStorage.
   ============================================================ */
function ColorBar({ width = 200, height = 20, style = {} }) {
  const bars = ["#00aedb", "#f37735", "#ffc425", "#1a1714", "#c5573a", "#1f5d62"];

  /* On first mount of any ColorBar instance, restore the saved accent */
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("vastola.accent");
      if (saved) document.documentElement.style.setProperty("--accent", saved);
    } catch (e) { /* ignore */ }
  }, []);

  function pick(color) {
    document.documentElement.style.setProperty("--accent", color);
    try { localStorage.setItem("vastola.accent", color); } catch (e) {}
  }

  return (
    <div
      role="group"
      aria-label="Accent color palette"
      style={{ display: "flex", width, height, border: "1px solid var(--ink)", ...style }}>
      {bars.map((c, i) => (
        <button
          key={i}
          type="button"
          onClick={() => pick(c)}
          aria-label={`Set accent color to ${c}`}
          title="Click to set accent color"
          style={{
            flex: 1,
            background: c,
            border: "none",
            padding: 0,
            margin: 0,
            cursor: "pointer",
            transition: "transform .15s ease, filter .15s ease",
          }}
          onMouseEnter={(e) => { e.currentTarget.style.filter = "brightness(1.15)"; }}
          onMouseLeave={(e) => { e.currentTarget.style.filter = "none"; }}
          onMouseDown={(e) => { e.currentTarget.style.transform = "scaleY(0.85)"; }}
          onMouseUp={(e) => { e.currentTarget.style.transform = "none"; }}
        />
      ))}
    </div>);
}

/* ============================================================
   <Star /> — burst (zine "NEW!" style)
   ============================================================ */
function Burst({ size = 140, points = 18, color = "var(--accent)", style = {}, children }) {
  const pts = [];
  const cx = 50, cy = 50;
  const outer = 48, inner = 36;
  for (let i = 0; i < points * 2; i++) {
    const r = i % 2 === 0 ? outer : inner;
    const a = (i / (points * 2)) * Math.PI * 2 - Math.PI / 2;
    pts.push(`${cx + Math.cos(a) * r},${cy + Math.sin(a) * r}`);
  }
  return (
    <div style={{ position: "relative", width: size, height: size, display: "inline-block", ...style }}>
      <svg width={size} height={size} viewBox="0 0 100 100" style={{ display: "block" }} aria-hidden="true">
        <polygon points={pts.join(" ")} fill={color} />
      </svg>
      <div
        style={{
          position: "absolute",
          inset: 0,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          color: "var(--paper)",
          fontFamily: "var(--font-loud)",
          fontSize: size * 0.16,
          textAlign: "center",
          padding: "0 12px",
          textTransform: "uppercase",
          lineHeight: 0.95,
        }}
      >
        {children}
      </div>
    </div>
  );
}

/* ============================================================
   <Arrow /> — hand-drawn arrow
   ============================================================ */
function Arrow({ width = 120, height = 60, color = "var(--accent)", style = {}, curve = "right" }) {
  const paths = {
    right: "M 6 30 Q 60 8, 108 32",
    left: "M 108 30 Q 60 8, 12 32",
    down: "M 30 6 Q 6 60, 32 108",
    up:   "M 30 108 Q 6 60, 32 6",
    squiggle: "M 6 30 Q 30 6, 50 30 T 90 30 T 110 32",
  };
  const head = {
    right: "M 100 22 L 110 32 L 96 38",
    left: "M 22 22 L 12 32 L 26 38",
    down: "M 22 100 L 32 110 L 38 96",
    up: "M 22 16 L 32 6 L 38 22",
    squiggle: "M 100 22 L 112 32 L 98 38",
  };
  return (
    <svg width={width} height={height} viewBox="0 0 120 60" style={style} aria-hidden="true">
      <path d={paths[curve]} stroke={color} strokeWidth="2.2" fill="none" strokeLinecap="round" />
      <path d={head[curve]} stroke={color} strokeWidth="2.2" fill="none" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

/* ============================================================
   <Underline /> — hand-drawn marker underline
   ============================================================ */
function Underline({ width = 200, color = "var(--accent)", style = {} }) {
  return (
    <svg width={width} height="10" viewBox="0 0 200 10" style={{ display: "block", ...style }} aria-hidden="true">
      <path
        d="M 4 6 Q 50 2, 100 5 T 196 5"
        stroke={color}
        strokeWidth="3"
        fill="none"
        strokeLinecap="round"
        opacity="0.85"
      />
    </svg>
  );
}

/* ============================================================
   <CircledNumber /> — handwritten circled number
   ============================================================ */
function CircledNumber({ n, size = 48, color = "var(--accent)" }) {
  return (
    <span style={{ position: "relative", display: "inline-block", width: size, height: size, textAlign: "center" }}>
      <svg width={size} height={size} viewBox="0 0 50 50" style={{ position: "absolute", inset: 0 }} aria-hidden="true">
        <ellipse cx="25" cy="25" rx="22" ry="20" fill="none" stroke={color} strokeWidth="2" transform="rotate(-6 25 25)" />
      </svg>
      <span
        style={{
          position: "relative",
          fontFamily: "var(--font-display)",
          fontWeight: 900,
          fontStyle: "italic",
          fontSize: size * 0.55,
          lineHeight: `${size}px`,
          color: color,
        }}
      >{n}</span>
    </span>
  );
}

Object.assign(window, {
  Bloom, Splatter, Halftone, RegistrationMark, ColorBar, Burst, Arrow, Underline, CircledNumber, mulberry,
});
