/* global React, ArtCanvas */
const { useState, useCallback, useEffect, useRef } = React;

const V2_DARK = { bg: '#0B0B0A', ink: '#E8E5DC', accent: '#9BE564', accent2: '#FF3D8B' };
const V2_VORONOI = { bg: '#0B0B0A', ink: '#E8E5DC', palette: ['#9BE564', '#FF3D8B', '#E0A93B', '#4FC3F7', '#141413', '#2A2823'] };
const V2_CIRCLE = { bg: '#0B0B0A', ink: '#E8E5DC', palette: ['#E8E5DC', '#9BE564', '#FF3D8B', '#E0A93B', '#4FC3F7'] };

function engineOpts(engine, seed) {
  const base = engine === 'voronoi' ? V2_VORONOI : engine === 'circlePack' ? V2_CIRCLE : V2_DARK;
  return seed != null ? { ...base, seed } : base;
}

const HERO_ENGINES = [
  { engine: 'flowField', label: 'FLOW FIELD' },
  { engine: 'voronoi', label: 'VORONOI' },
  { engine: 'curlFluid', label: 'CURL FLUID' },
  { engine: 'warp', label: 'DOMAIN WARP' },
  { engine: 'contour', label: 'CONTOUR' },
  { engine: 'waveInterference', label: 'WAVE' },
  { engine: 'displacement', label: 'DISPLACEMENT' },
  { engine: 'plasma', label: 'PLASMA' },
  { engine: 'fractal', label: 'JULIA SET' },
  { engine: 'gameOfLife', label: 'GAME OF LIFE' },
  { engine: 'knn', label: 'KNN' },
  { engine: 'lsystem', label: 'L-SYSTEM' },
  { engine: 'circlePack', label: 'SHAPE PACK' },
  { engine: 'subdivision', label: 'SUBDIVISION' },
  { engine: 'tessellation', label: 'TESSELLATION' },
  { engine: 'stripes', label: 'WEFT' },
];

const V2_WORKS = [
  {
    id: '0x01', title: 'sigil_run_447.svg', engine: 'flowField', tag: 'motion graphics', stat: 'iter 4470 · seed 0x4A7B',
    specs: { particles: 320, scale: '.004', octaves: 4, damping: '.92', speed: '.9' },
    output: 'SVG · 1024×1024', edition: '∞ variants · 1 ruleset', runtime: '14ms/frame',
    note: '// a flow-field identity engine.\n// every run draws a new sigil\n// from a seeded noise field.',
  },
  {
    id: '0x02', title: 'voronoi_atlas.png', engine: 'voronoi', tag: 'editorial', stat: 'cells 32 · ε 0.04',
    specs: { points: 28, metric: 'euclidean', lloyd: 'on', jitter: '.04', step: '6px' },
    output: 'PNG · 2048×2048', edition: '∞ variants · 1 ruleset', runtime: '8ms/frame',
    note: '// partition space by proximity.\n// cells drift, collide, reform.\n// borders emerge from distance.',
  },
  {
    id: '0x03', title: 'pack_recursive.svg', engine: 'circlePack', tag: 'print', stat: 'shapes 612 · packed 0.91',
    specs: { maxShapes: 600, maxRadius: '80px', minRadius: '3px', shapes: 'mixed', density: '.91' },
    output: 'SVG · vector', edition: '∞ variants · 10 shape modes', runtime: '~4 shapes/frame',
    note: '// greedy non-overlapping packing.\n// circles, squares, triangles,\n// diamonds, hexagons, stars.',
  },
  {
    id: '0x04', title: 'hilbert_fill.svg', engine: 'lsystem', tag: 'architectural', stat: 'order 5 · 1023 segs',
    specs: { iterations: '4–6', angle: '90°', rules: '5 variants', fill: 'space-filling', origin: 'fitted' },
    output: 'SVG · scale-free', edition: '∞ variants · 5 rulesets', runtime: 'progressive draw',
    note: '// hilbert space-filling curve.\n// a single continuous path that\n// visits every cell in the grid.',
  },
  {
    id: '0x05', title: 'game_of_life.png', engine: 'gameOfLife', tag: 'cellular automata', stat: 'cells ∞ · B3/S23',
    specs: { cellSize: '6px', rule: 'B3/S23', wrap: 'toroidal', density: '30%', stepRate: '15fps' },
    output: 'canvas · live', edition: '∞ variants · 1 ruleset', runtime: '~1ms/step',
    note: '// Conway\'s game of life.\n// simple rules, emergent order.\n// hover injects new cells.',
  },
  {
    id: '0x06', title: 'modulated_weft.svg', engine: 'stripes', tag: 'textile', stat: 'lines 60 · phase π/3',
    specs: { lines: 60, amplitude: '1.5×', noiseScale: '.005', phase: 'animated', lineWidth: '.6×step' },
    output: 'SVG · tileable', edition: '∞ variants · 1 ruleset', runtime: '2ms/frame',
    note: '// sinusoidal lines warped\n// by perlin noise. riso-style\n// abstraction for textile.',
  },
];

const V2_USES = [
  { n: '01', title: 'Identity Systems', desc: 'Logos that mutate while staying recognizable. Each variant is seeded from brand parameters — color, proportion, rhythm — so the mark feels alive but never off-brand. Scales from favicon to billboard.' },
  { n: '02', title: 'Editorial Covers', desc: 'Manuscript-tuned algorithms for print. We feed the text — word count, sentiment, structure — into the generator. The cover becomes a visual fingerprint of the content it wraps. Every edition is unique.' },
  { n: '03', title: 'NFT / On-chain', desc: 'Deterministic from token seed. Fully on-chain, no external dependencies. The contract stores the algorithm; the token ID drives the output. Archival by design — runs the same in 50 years.' },
  { n: '04', title: 'Print Editions', desc: 'Pen plotter and giclée on archival cotton rag. Each piece is a one-of-one output from a shared ruleset. Signed, numbered, shipped flat. Previous runs sold through Artsy and Uprise Art.' },
  { n: '05', title: 'Motion Graphics', desc: 'Stochastic timing with deterministic replay. Same seed, same film — frame-perfect across renders. Used for title sequences, interstitials, and live stage visuals. Exports to 4K ProRes or real-time WebGL.' },
  { n: '06', title: 'Architectural', desc: 'Projection mapping, glass etching, woven façade panels. The algorithm adapts to site geometry — sun path, foot traffic, structural grid. Outputs range from CNC files to real-time LED control signals.' },
  { n: '07', title: 'Textile Patterns', desc: 'Tileable surfaces for jacquard looms, digital knit, and screen print. Repeat logic is baked into the generator so edges always match. Delivered as production-ready files with colorway variants.' },
  { n: '08', title: 'Data Vis', desc: 'Editorial information graphics where the data shapes the aesthetic. We build custom visual languages — not standard charts — that encode meaning through density, rhythm, and color. Published in NYT, Bloomberg, and Monocle.' },
  { n: '09', title: 'Album Artwork', desc: 'The sleeve is drawn from the audio. We analyze frequency, tempo, and structure to seed the generator. Physical editions get unique covers; digital gets animated loops. Collaborations with 4AD, Warp, and Ghostly.' },
  { n: '10', title: 'Packaging', desc: 'Variable cover systems where no two units are alike. The algorithm generates within brand constraints — same palette, same density, different composition every time. Ideal for limited runs, seasonal drops, and collector editions.' },
];

const V2_ALGOS = [
  { id: 'gen.voronoi', name: 'Voronoi', engine: 'voronoi', desc: 'Partition space by proximity to seed points.', params: [{l:'metric',on:true},{l:'lloyd',on:true},{l:'jitter',on:false}] },
  { id: 'gen.flow', name: 'Flow Field', engine: 'flowField', desc: 'Particles trace a Perlin gradient field.', params: [{l:'octaves',on:true},{l:'curl',on:false},{l:'wrap',on:true}] },
  { id: 'gen.lsystem', name: 'L-System', engine: 'lsystem', desc: 'Hilbert space-filling curve via recursive rewriting.', params: [{l:'order',on:true},{l:'variant',on:true},{l:'fill',on:true}] },
  { id: 'gen.pack', name: 'Recursive Pack', engine: 'circlePack', desc: 'Greedy non-overlapping packing.', params: [{l:'palette',on:true},{l:'density',on:true},{l:'masked',on:false}] },
  { id: 'gen.life', name: 'Game of Life', engine: 'gameOfLife', desc: 'Conway\'s cellular automata. Emergent complexity from simple rules.', params: [{l:'B3/S23',on:true},{l:'wrap',on:true},{l:'inject',on:true}] },
  { id: 'gen.weft', name: 'Modulated Weft', engine: 'stripes', desc: 'Sinusoidal lines, noise-warped.', params: [{l:'phase',on:true},{l:'amplitude',on:true},{l:'riso',on:true}] },
  { id: 'gen.subdiv', name: 'Subdivision', engine: 'subdivision', desc: 'Recursive rectangle splitting. Mondrian composition.', params: [{l:'depth',on:true},{l:'fill',on:true},{l:'bias',on:true}] },
  { id: 'gen.tess', name: 'Tessellation', engine: 'tessellation', desc: 'Repeating geometric tiles — triangles, hexagons, diamonds.', params: [{l:'type',on:true},{l:'size',on:true},{l:'color',on:true}] },
  { id: 'gen.plasma', name: 'Plasma', engine: 'plasma', desc: 'Sine-wave interference, palette-mapped color fields.', params: [{l:'freq',on:true},{l:'feedback',on:true},{l:'phase',on:true}] },
  { id: 'gen.fractal', name: 'Julia Set', engine: 'fractal', desc: 'Complex-plane fractal with animated c-parameter drift.', params: [{l:'c-real',on:true},{l:'c-imag',on:true},{l:'iter',on:true}] },
  { id: 'gen.displace', name: 'Displacement', engine: 'displacement', desc: 'Noise-displaced color bands. Tectonic drift.', params: [{l:'bands',on:true},{l:'noise',on:true},{l:'mouse',on:true}] },
  { id: 'gen.contour', name: 'Contour', engine: 'contour', desc: 'Topographic iso-lines via marching squares.', params: [{l:'levels',on:true},{l:'step',on:true},{l:'peak',on:true}] },
  { id: 'gen.knn', name: 'KNN', engine: 'knn', desc: 'K-nearest neighbor clustering. Points drift and re-cluster.', params: [{l:'k',on:true},{l:'points',on:true},{l:'attract',on:true}] },
  { id: 'gen.warp', name: 'Domain Warp', engine: 'warp', desc: 'Nested noise layers — coordinates fed through noise.', params: [{l:'layers',on:true},{l:'scale',on:true},{l:'drift',on:true}] },
  { id: 'gen.curl', name: 'Curl Fluid', engine: 'curlFluid', desc: 'Divergence-free particle flow. Swirling, fluid patterns.', params: [{l:'curl',on:true},{l:'vortex',on:true},{l:'density',on:true}] },
  { id: 'gen.wave', name: 'Wave', engine: 'waveInterference', desc: 'Overlapping circular waves. Interference patterns.', params: [{l:'sources',on:true},{l:'freq',on:true},{l:'drift',on:true}] },
];

// --- Modal ---
function WorkModal({ work, onClose }) {
  useEffect(() => {
    function onKey(e) { if (e.key === 'Escape') onClose(); }
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = '';
    };
  }, [onClose]);

  const algo = V2_ALGOS.find(a => a.engine === work.engine);
  const opts = engineOpts(work.engine);

  // extract palette colors for swatches
  const swatches = opts.palette
    ? [opts.bg, opts.ink, ...opts.palette]
    : [opts.bg, opts.ink, opts.accent, opts.accent2].filter(Boolean);

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}>✕ CLOSE</button>

        <div className="modal-canvas">
          <ArtCanvas engine={work.engine} opts={opts} />
          <div className="modal-canvas-hint">
            <span>HOVER · PERTURB FIELD</span>
            <span>CLICK · RESEED + RECOLOR</span>
          </div>
        </div>

        <aside className="modal-meta">
          {/* --- header --- */}
          <div className="modal-label"><span>OUTPUT</span><span>{work.id}</span></div>
          <div className="modal-title">{work.title}</div>

          {/* --- engine readings --- */}
          <div className="modal-label"><span>ENGINE</span><span style={{color:'#9BE564'}}>● LIVE</span></div>
          <div className="modal-reading">
            <span>ENGINE</span><span>{work.engine}</span>
            <span>USE CASE</span><span>{work.tag}</span>
            <span>STATS</span><span>{work.stat}</span>
            <span>FRAMERATE</span><span>60.00 fps</span>
            <span>RENDERER</span><span>canvas 2D</span>
            <span>DEPENDENCIES</span><span>zero</span>
          </div>
          <div className="modal-bar"><i style={{width:'72%'}} /></div>

          {/* --- engine-specific params --- */}
          {work.specs && (
            <>
              <div className="modal-label"><span>PARAMETERS</span><span>{Object.keys(work.specs).length}</span></div>
              <div className="modal-reading">
                {Object.entries(work.specs).map(([k, v]) => (
                  <React.Fragment key={k}>
                    <span>{k.toUpperCase()}</span><span>{v}</span>
                  </React.Fragment>
                ))}
              </div>
            </>
          )}

          {/* --- output / format --- */}
          <div className="modal-label"><span>OUTPUT</span><span>FORMAT</span></div>
          <div className="modal-reading">
            <span>FORMAT</span><span>{work.output}</span>
            <span>EDITION</span><span>{work.edition}</span>
            <span>RENDER</span><span>{work.runtime}</span>
            <span>SEED</span><span>random · click to reseed</span>
          </div>

          {/* --- algorithm --- */}
          {algo && (
            <>
              <div className="modal-label"><span>ALGORITHM</span><span>{algo.id}</span></div>
              <div className="modal-algo-name">{algo.name}<span className="ext">.exe</span></div>
              <div className="modal-algo-desc">{algo.desc}</div>
              <div className="modal-params">
                {algo.params.map(p => (
                  <span key={p.l} className={`param ${p.on ? 'on' : ''}`}>{p.on ? '◉ ' : '○ '}{p.l}</span>
                ))}
              </div>
            </>
          )}

          {/* --- palette swatches --- */}
          <div className="modal-label"><span>PALETTE</span><span>{swatches.length} COLORS</span></div>
          <div className="modal-swatches">
            {swatches.map((c, i) => (
              <div key={i} className="modal-swatch" title={c}>
                <span className="modal-swatch-color" style={{background: c}} />
                <span className="modal-swatch-hex">{c}</span>
              </div>
            ))}
          </div>

          {/* --- console --- */}
          {work.note && (
            <>
              <div className="modal-label"><span>CONSOLE</span><span>STDOUT</span></div>
              <div className="modal-console">
                {work.note.split('\n').map((line, i) => (
                  <div key={i}>{line}</div>
                ))}
                <div><span style={{color:'#9BE564'}}>$</span> <span style={{color:'#9BE564'}}>_</span></div>
              </div>
            </>
          )}
        </aside>
      </div>
    </div>
  );
}

// --- Main page ---
function V2() {
  const [modal, setModal] = useState(null);
  const closeModal = useCallback(() => setModal(null), []);
  const [heroIdx, setHeroIdx] = useState(0);
  const heroHover = useRef(false);

  useEffect(() => {
    const id = setInterval(() => {
      if (!heroHover.current) setHeroIdx(i => (i + 1) % HERO_ENGINES.length);
    }, 6000);
    return () => clearInterval(id);
  }, []);

  return (
    <div className="alorro-page v2" data-screen-label="V2 Terminal">
      <div className="topbar">
        <a href="index.html" className="home"><span className="dot" />ALORRO-LABS</a>
        <div className="nav">
          <a>~/works</a>
          <a>~/catalog</a>
          <a>~/studio</a>
          <a>~/commissions</a>
          <a>~/journal</a>
        </div>
        <div className="clock">UTC −7 · 14:08:42</div>
        <div className="cmd">SEARCH<kbd>⌘K</kbd></div>
      </div>

      <section className="hero">
        <div className="hero-left">
          <div className="label-row"><span>SESSION</span><span>0x4A7B…3C9D</span></div>
          <div className="reading">
            <span>RUNTIME</span><span>00:14:08.421</span>
            <span>FRAMERATE</span><span>60.00 fps</span>
            <span>PARTICLES</span><span>320 active</span>
            <span>SEED</span><span>0x4A7B3C9D</span>
            <span>NOISE OCT.</span><span>4</span>
            <span>FIELD SCALE</span><span>0.004</span>
          </div>
          <div className="bar"><i style={{width:'72%'}} /></div>
          <div style={{color:'#908C7F', fontSize:10, marginTop:24, lineHeight:1.6}}>
            $ alorro init field<br/>
            ↳ field initialized<br/>
            $ alorro tick --particles=320<br/>
            ↳ ok. moving.<br/>
            $ <span style={{color:'#9BE564'}}>_</span>
          </div>
        </div>
        <div className="hero-canvas-wrap"
             onMouseEnter={() => { heroHover.current = true; }}
             onMouseLeave={() => { heroHover.current = false; }}>
          <div className="hero-carousel">
            {HERO_ENGINES.map((e, i) => (
              <div key={e.engine} className={`hero-slide ${i === heroIdx ? 'active' : ''}`}>
                <ArtCanvas engine={e.engine} opts={engineOpts(e.engine)} />
              </div>
            ))}
          </div>
          <button className="hero-arrow hero-prev" onClick={() => setHeroIdx(i => (i - 1 + HERO_ENGINES.length) % HERO_ENGINES.length)}>←</button>
          <button className="hero-arrow hero-next" onClick={() => setHeroIdx(i => (i + 1) % HERO_ENGINES.length)}>→</button>
          <div className="hero-indicators">
            {HERO_ENGINES.map((e, i) => (
              <button key={e.engine} className={i === heroIdx ? 'active' : ''} onClick={() => setHeroIdx(i)} title={e.label} />
            ))}
          </div>
          <div className="hero-overlay">
            <div>
              <div style={{color:'#908C7F', fontSize:11, textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:24}}>
                ALORRO LABS // GENERATIVE STUDIO // EST.2019
              </div>
              <div className="hero-title">
                ALGORITHMS<br/>
                AS <span className="accent">AUTHOR</span>.<br/>
                IMAGE AS<br/>
                <span className="accent">RESIDUE</span>.
              </div>
            </div>
            <div className="hero-foot">
              <span>HOVER · INTERACT · CLICK RESEEDS</span>
              <span className="hero-engine-label">{HERO_ENGINES[heroIdx].label}</span>
              <span>↓ INDEX FOLLOWS</span>
            </div>
          </div>
        </div>
        <div className="hero-right">
          <div className="label-row"><span>OUTPUTS</span><span>168 TOTAL</span></div>
          <div style={{display:'grid', gridTemplateColumns:'1fr', gap:6, fontSize:10.5, color:'#C8C4BA'}}>
            <div>→ AL-001 · cipher_bloom.svg</div>
            <div>→ AL-002 · tessera.png</div>
            <div>→ AL-003 · game_of_life.svg</div>
            <div>→ AL-004 · lattice_pack.svg</div>
            <div>→ AL-005 · hyssop.svg</div>
            <div>→ AL-006 · stratum_weft.svg</div>
            <div>→ AL-007 · …</div>
          </div>
          <div className="label-row" style={{marginTop:32}}><span>EXHIBITS</span><span>11</span></div>
          <div style={{fontSize:10.5, color:'#C8C4BA', lineHeight:1.7}}>
            v&amp;a · 2024<br/>
            cooper hewitt · 2025<br/>
            haus der kunst · 2025
          </div>
        </div>
      </section>

      <div className="ticker">
        <div className="ticker-track">
          {[...Array(2)].map((_, k) => (
            <React.Fragment key={k}>
              <span className="hl">● LIVE</span>
              <span>SESSION 0x4A7B3C9D</span>
              <span>FIELD AT 0.72</span>
              <span className="hl">● 168 OUTPUTS ARCHIVED</span>
              <span>NEXT DROP 06.07.2026</span>
              <span>OPEN COMMISSIONS · Q3</span>
              <span className="hl">● V&amp;A — ALGORITHM AS AUTHOR — RUNS THRU AUG</span>
              <span>· · ·</span>
            </React.Fragment>
          ))}
        </div>
      </div>

      <section className="section">
        <div className="section-head">
          <div className="num">// I. SELECTED.WORKS</div>
          <h2>OUTPUT/<span style={{color:'#9BE564'}}>0x</span></h2>
          <div className="meta">2024 — 2026<br/>168 ARCHIVED · 6 SHOWN</div>
        </div>
        <div className="works">
          {V2_WORKS.map((w) => (
            <div key={w.id} className="work" style={{cursor:'pointer'}} onClick={() => setModal(w)}>
              <div className="frame">
                <ArtCanvas engine={w.engine} opts={engineOpts(w.engine)} />
              </div>
              <div className="body">
                <div className="ttl">{w.title}</div>
                <div className="id">{w.id}</div>
                <div className="tag">[{w.tag}]</div>
                <div className="stats"><span>{w.stat}</span></div>
              </div>
            </div>
          ))}
        </div>
      </section>

      <section className="uses">
        <div className="section-head">
          <div className="num">// II. USE.CASES</div>
          <h2>WHERE/<span style={{color:'#9BE564'}}>10</span></h2>
          <div className="meta">DOMAINS WE WORK IN</div>
        </div>
        <div className="uses-grid">
          {V2_USES.map((u) => (
            <div key={u.n} className="use">
              <div>
                <div className="n">[{u.n}]</div>
                <h3>{u.title}</h3>
              </div>
              <p>{u.desc}</p>
            </div>
          ))}
        </div>
      </section>

      <section className="section">
        <div className="section-head">
          <div className="num">// III. ALGORITHM.CATALOG</div>
          <h2>ENGINES/<span style={{color:'#9BE564'}}>16</span></h2>
          <div className="meta">EACH RUNS LIVE · HOVER<br/>TO PERTURB · CLICK RESEEDS</div>
        </div>
        <div className="algos">
          {V2_ALGOS.map((a) => (
            <div key={a.id} className="algo">
              <div className="vis">
                <ArtCanvas engine={a.engine} opts={engineOpts(a.engine, 77777)} />
              </div>
              <div className="body">
                <div className="h"><span>{a.id}</span><span style={{color:'#9BE564'}}>● LIVE</span></div>
                <h3>{a.name}</h3>
                <p>{a.desc}</p>
                <div className="params">
                  {a.params.map(p => <span key={p.l} className={`param ${p.on ? 'on' : ''}`}>{p.on ? '◉ ' : '○ '}{p.l}</span>)}
                </div>
              </div>
            </div>
          ))}
        </div>
      </section>

      <section className="manifesto">
        <div className="grid">
          <div className="lhs">// IV.<br/>// STUDIO.NOTE</div>
          <div>
            <p>
              the algorithm is the <span className="accent">collaborator</span>.
              we curate, prune, occasionally veto. every piece carries a seed,
              a ruleset, and the <em>residue of a hundred rejected runs</em>.
            </p>
            <p>
              medium: <span className="accent">computation</span>.<br/>
              output: image, object, garment, building.
            </p>
          </div>
        </div>
      </section>

      <footer>
        <div>
          <h4>SESSION</h4>
          0x4A7B3C9D<br/>
          PID 31415<br/>
          UPTIME 00:14:08
        </div>
        <div>
          <h4>STUDIOS</h4>
          NEW YORK CITY<br/>
          NY 11357<br/>
          UTC −5 (EST)
        </div>
        <div>
          <h4>CONTACT</h4>
          support@alorro.com<br/>
          IG: aalorro<br/>
          x.com: @balorro
        </div>
        <div>
          <h4>STACK</h4>
          js · webgl · plotter<br/>
          space grotesk · jb mono<br/>
          built in 2026
        </div>
        <div className="colophon">
          <div className="huge" style={{fontSize:'64px'}}>ALORRO-LABS//<span style={{color:'#9BE564'}}>2026</span></div>
        </div>
      </footer>

      {modal && <WorkModal work={modal} onClose={closeModal} />}
    </div>
  );
}

window.V2 = V2;
