/* global React */
const { useState: useStateD, useEffect: useEffectD, useRef: useRefD, useCallback: useCallbackD } = React;

// --- Brush set for the radial menu (the 8 ZBrush brushes for the demo) ----
// Some brushes have children that fan out on parent hover (Standard + Move).
// Children render in a secondary (cyan) accent so they read as sub-options.
const DEMO_BRUSHES = [
{ id: 'standard', name: 'Standard', res: 'brush-standard',
  children: [
  { id: 'damstandard', name: 'DamStandard', res: 'brush-damstandard' },
  { id: 'pinch', name: 'Pinch', res: 'brush-pinch' },
  { id: 'smooth', name: 'Smooth', res: 'brush-smooth' }]

},
{ id: 'move', name: 'Move', res: 'brush-move',
  children: [
  { id: 'move-2', name: 'Move', res: 'brush-move' },
  { id: 'move-topo', name: 'Move Topological', res: 'brush-movetopo' },
  { id: 'snakehook', name: 'SnakeHook', res: 'brush-snakehook' }]

},
{ id: 'hpolish', name: 'hPolish', res: 'brush-hpolish' },
{ id: 'claybuild', name: 'Clay BuildUp', res: 'brush-claybuildup' },
{ id: 'softpaint', name: 'Smooth', res: 'brush-smooth' },
{ id: 'curvetube', name: 'Clay Tubes', res: 'brush-claytubes' },
{ id: 'gio', name: 'Clay', res: 'brush-clay' },
{ id: 'inflate', name: 'Inflate', res: 'brush-inflate' }];


const getRes = (id) => window.__resources && window.__resources[id] || '';

// --- Lazy-load <spline-viewer> only once the section is near the viewport --
const useLazySplineLoader = (rootRef) => {
  const [ready, setReady] = useStateD(false);
  useEffectD(() => {
    if (ready) return;
    const node = rootRef.current;
    if (!node) return;
    let cancelled = false;
    const loadScript = () => {
      if (cancelled) return;
      if (window.customElements && window.customElements.get('spline-viewer')) {
        setReady(true);return;
      }
      if (document.querySelector('script[data-spline-viewer]')) {
        const check = () => {
          if (window.customElements && window.customElements.get('spline-viewer')) setReady(true);else
          setTimeout(check, 80);
        };
        check();
        return;
      }
      const s = document.createElement('script');
      s.type = 'module';
      s.src = 'https://unpkg.com/@splinetool/viewer@1.12.94/build/spline-viewer.js';
      s.setAttribute('data-spline-viewer', '1');
      s.onload = () => {if (!cancelled) setReady(true);};
      document.head.appendChild(s);
    };
    const io = new IntersectionObserver((entries) => {
      for (const e of entries) {
        if (e.isIntersecting) {loadScript();io.disconnect();break;}
      }
    }, { rootMargin: '600px 0px' });
    io.observe(node);
    return () => {cancelled = true;io.disconnect();};
  }, [ready, rootRef]);
  return ready;
};

// =============================================================================
// Wireframe ZBrush UI — based on the reference screenshot.
// Receives the current active brush so the "Standard" tile can re-render as
// the active brush thumbnail with an orange outline.
// =============================================================================
const ZB_TOP_MENU = [
'Alpha', 'Brush', 'Color', 'Document', 'Draw', 'Dynamics', 'Edit', 'File', 'Layer', 'Light',
'Macro', 'Marker', 'Material', 'Movie', 'Picker', 'Preferences', 'Render', 'Stencil',
'Stroke', 'Texture', 'Tool', 'Transform', 'Zplugin', 'ZScript', 'Help'];

const ZB_LEFT_TILES = [
{ label: 'Standard', isActive: true }, /* this tile shows the active brush */
{ label: 'Dots' },
{ label: '~BrushAlpha' },
{ label: 'Texture Off' },
{ label: 'MatCap Gray' }];

const ZB_LEFT_RAIL_ICONS = [
'Scroll', 'Zoom', 'Actual', 'AAHalf', 'Persp', 'Floor', 'L.Sym', 'XYZ'];

const ZB_RIGHT_RAIL_ICONS = [
'BPR', 'SPix', 'Scroll', 'Zoom', 'Actual', 'AAHalf', 'Persp', 'Floor', 'XYZ', 'Frame', 'Move', 'Zoom3D', 'Rotate', 'Transp'];

const ZB_TOOL_LIST = [
'SubTool', 'Geometry', 'ArrayMesh', 'NanoMesh', 'Slime Bridge', 'Thick Skin', 'Layers',
'FiberMesh', 'Geometry HD', 'Preview', 'Surface', 'Deformation', 'Masking', 'Visibility',
'Polygroups', 'Contact', 'Morph Target', 'Polypaint', 'UV Map', 'Texture Map',
'Displacement Map', 'Normal Map', 'Vector Displacement Map', 'Display Properties',
'Unified Skin', 'Initialize'];


const ZBrushWireframe = ({ activeBrush, flashing }) =>
<div className="zb-wire" aria-hidden="true">
    <div className="zb-menubar">
      {ZB_TOP_MENU.map((m, i) =>
    <span key={i} className="zb-menubar-item">{m}</span>
    )}
    </div>

    <div className="zb-toolbar">
      <div className="zb-toolbar-group">
        <span className="zb-pill" />
        <span className="zb-pill" />
        <span className="zb-pill" />
      </div>
      <div className="zb-toolbar-group zb-toolbar-group--actions">
        <span className="zb-tile zb-tile--active" />
        <span className="zb-tile zb-tile--active" />
        <span className="zb-tile" />
        <span className="zb-tile" />
        <span className="zb-tile" />
        <span className="zb-tile zb-tile--orb" />
        <span className="zb-tile zb-tile--orb" />
      </div>
      <div className="zb-toolbar-group">
        <span className="zb-toolbar-tag" />
        <span className="zb-toolbar-tag zb-toolbar-tag--active" />
        <span className="zb-toolbar-tag" />
        <span className="zb-toolbar-tag" />
        <span className="zb-toolbar-tag zb-toolbar-tag--active" />
        <span className="zb-toolbar-tag" />
      </div>
      <div className="zb-toolbar-group">
        <span className="zb-slider" />
        <span className="zb-slider" />
      </div>
      <div className="zb-toolbar-group zb-toolbar-group--meta">
        <span className="zb-pill zb-pill--sm" />
        <span className="zb-pill zb-pill--sm" />
      </div>
    </div>

    <div className="zb-progress" />

    <div className="zb-left-shelf">
      {ZB_LEFT_TILES.map((t, i) =>
    <div
      key={i}
      className={`zb-bigtile ${t.isActive ? 'zb-bigtile--active' : ''} ${t.isActive && flashing ? 'is-flashing' : ''}`}
      data-key={t.label}>
      
          {t.isActive ?
      <span className="zb-bigtile-active-img" key={activeBrush.id /* re-mount on change for a quick pop */}>
              <img src={getRes(activeBrush.res)} alt="" />
            </span> :

      <span className="zb-bigtile-glyph" />
      }
          <span className="zb-bigtile-label">{t.isActive ? activeBrush.name : t.label}</span>
        </div>
    )}
      <div className="zb-color-block">
        <div className="zb-color-wheel" />
        <span className="zb-color-label">Gradient</span>
      </div>
      <div className="zb-color-swatch">
        <span className="zb-swatch-black" />
        <span className="zb-swatch-white" />
        <span className="zb-color-label">SwitchColor</span>
      </div>
      <div className="zb-alt-pill">Alternate</div>
    </div>

    <div className="zb-left-rail">
      {ZB_LEFT_RAIL_ICONS.map((label, i) =>
    <div key={i} className="zb-rail-cell">
          <span className="zb-rail-icon" />
          <span className="zb-rail-label">{label}</span>
        </div>
    )}
    </div>

    <div className="zb-right-rail">
      {ZB_RIGHT_RAIL_ICONS.map((label, i) =>
    <div key={i} className="zb-rail-cell">
          <span className="zb-rail-icon" />
          <span className="zb-rail-label">{label}</span>
        </div>
    )}
    </div>

    <div className="zb-right-panel">
      <div className="zb-tool-header">
        <span className="zb-tool-mark" />
        <span className="zb-tool-title">Tool</span>
        <span className="zb-tool-refresh" />
      </div>
      <div className="zb-btn-grid">
        {Array.from({ length: 18 }, (_, i) =>
      <span key={i} className={`zb-btn ${i === 0 ? 'zb-btn--active' : ''}`} />
      )}
      </div>
      <div className="zb-thumb-row">
        {Array.from({ length: 5 }, (_, i) =>
      <span key={i} className={`zb-thumb ${i === 0 ? 'zb-thumb--active' : ''}`} />
      )}
      </div>
      <div className="zb-tool-list">
        {ZB_TOOL_LIST.map((label, i) =>
      <div key={i} className={`zb-tool-row ${label === 'XYZ' ? 'zb-tool-row--active' : ''}`}>
            <span className="zb-tool-row-label">{label}</span>
          </div>
      )}
      </div>
    </div>

    <div className="zb-canvas-frame" />
  </div>;


// =============================================================================
// Radial menu — perfect-circle slots, scaled 10% up, blue children on hover.
// Children only appear when their parent slot is hovered (one parent at a time).
// =============================================================================
const RADIAL_RADIUS = 125;
const RADIAL_SLOT = 70;
const CHILD_DIST = 112; // bumped from 92 — more space between parent + children
const CHILD_SPREAD = 0.55; // bumped from 0.42 — wider fan
const CHILD_SLOT = 54;

const RadialOverlay = ({ x, y, onPick, onCancel, canvasRect }) => {
  const [hoverParent, setHoverParent] = useStateD(null);
  const closeTimerRef = useRefD(null);

  const requestOpen = useCallbackD((id) => {
    if (closeTimerRef.current) {
      clearTimeout(closeTimerRef.current);
      closeTimerRef.current = null;
    }
    setHoverParent(id);
  }, []);

  const requestClose = useCallbackD((id) => {
    if (closeTimerRef.current) clearTimeout(closeTimerRef.current);
    closeTimerRef.current = setTimeout(() => {
      setHoverParent((cur) => cur === id ? null : cur);
    }, 110);
  }, []);

  // Clean up the timer on unmount
  useEffectD(() => () => {
    if (closeTimerRef.current) clearTimeout(closeTimerRef.current);
  }, []);

  // Clamp the menu so it stays inside the canvas, accounting for the further
  // child fan.
  const pad = RADIAL_RADIUS + RADIAL_SLOT / 2 + CHILD_DIST + 28;
  const cx = Math.max(pad, Math.min(canvasRect.width - pad, x));
  const cy = Math.max(pad, Math.min(canvasRect.height - pad, y));

  const slots = DEMO_BRUSHES.map((b, i) => {
    const a = i / DEMO_BRUSHES.length * Math.PI * 2 - Math.PI / 2;
    return { ...b, angle: a, dx: Math.cos(a) * RADIAL_RADIUS, dy: Math.sin(a) * RADIAL_RADIUS };
  });

  const half = RADIAL_RADIUS + RADIAL_SLOT / 2 + CHILD_DIST + 16;

  return (
    <div className="rz-overlay" style={{ left: 0, top: 0 }}>
      <div
        className="rz-overlay-plate"
        onClick={(e) => {e.stopPropagation();onCancel();}}
        style={{
          left: cx - half,
          top: cy - half,
          width: half * 2,
          height: half * 2
        }}>
        
        <svg className="rz-overlay-svg" viewBox={`${-half} ${-half} ${half * 2} ${half * 2}`} width={half * 2} height={half * 2}>
          <defs>
            <radialGradient id="rz-center-glow" cx="50%" cy="50%" r="50%">
              <stop offset="0%" stopColor="#f0651f" stopOpacity="0.40" />
              <stop offset="55%" stopColor="#f0651f" stopOpacity="0.10" />
              <stop offset="100%" stopColor="#f0651f" stopOpacity="0" />
            </radialGradient>
          </defs>
          <circle cx="0" cy="0" r={RADIAL_RADIUS * 0.95} fill="url(#rz-center-glow)" />
          {slots.map((s, i) =>
          <line key={i}
          x1="0" y1="0"
          x2={s.dx} y2={s.dy}
          stroke="#f0651f" strokeWidth="1.4"
          strokeDasharray="3 5" strokeLinecap="round"
          opacity="0.85" />

          )}
          <circle cx="0" cy="0" r={RADIAL_RADIUS} fill="none" stroke="rgba(240,101,31,0.18)" strokeWidth="1" />
        </svg>

        <div className="rz-center">
          <span className="rz-center-label rz-center-label--top">MY BRUSHES</span>
          <span className="rz-center-dot" />
          <span className="rz-center-label rz-center-label--bot">CLICK TO CANCEL</span>
        </div>

        {slots.map((s, i) =>
        <RadialSlot
          key={s.id}
          slot={s}
          half={half}
          isOpen={hoverParent === s.id}
          onRequestOpen={requestOpen}
          onRequestClose={requestClose}
          onPick={onPick}
          animDelay={i * 22} />

        )}
      </div>
    </div>);

};

const RadialSlot = ({ slot, half, isOpen, onRequestOpen, onRequestClose, onPick, animDelay }) => {
  const hasChildren = !!(slot.children && slot.children.length);
  const childPositions = (slot.children || []).map((c, i, arr) => {
    const offset = (i - (arr.length - 1) / 2) * CHILD_SPREAD;
    const a = slot.angle + offset;
    return {
      ...c,
      dx: slot.dx + Math.cos(a) * CHILD_DIST,
      dy: slot.dy + Math.sin(a) * CHILD_DIST,
      parentDx: slot.dx,
      parentDy: slot.dy
    };
  });

  return (
    <div className={`rz-slot-group ${isOpen ? 'is-open' : ''}`}>
      {hasChildren &&
      <svg
        className="rz-child-spokes"
        viewBox={`${-half} ${-half} ${half * 2} ${half * 2}`}
        width={half * 2} height={half * 2}
        aria-hidden="true">
        
          {childPositions.map((c, i) =>
        <line key={i}
        x1={c.parentDx} y1={c.parentDy}
        x2={c.dx} y2={c.dy}
        stroke="#4dc8e9" strokeWidth="1.2"
        strokeDasharray="3 5" strokeLinecap="round"
        opacity={isOpen ? 0.85 : 0}
        style={{ transition: 'opacity .2s' }} />

        )}
        </svg>
      }

      <button
        type="button"
        className="rz-slot rz-slot--parent"
        style={{
          left: half + slot.dx,
          top: half + slot.dy,
          width: RADIAL_SLOT + 8,
          height: RADIAL_SLOT + 36,
          animationDelay: `${animDelay}ms`
        }}
        onMouseEnter={() => hasChildren && onRequestOpen(slot.id)}
        onMouseLeave={() => hasChildren && onRequestClose(slot.id)}
        onFocus={() => hasChildren && onRequestOpen(slot.id)}
        onBlur={() => hasChildren && onRequestClose(slot.id)}
        onClick={(e) => {e.stopPropagation();onPick(slot);}}>
        
        <span className="rz-slot-disc" style={{ width: RADIAL_SLOT, height: RADIAL_SLOT }}>
          <img src={getRes(slot.res)} alt="" draggable="false" />
        </span>
        <span className="rz-slot-label">{slot.name}</span>
        {hasChildren && <span className="rz-slot-has-children" aria-hidden="true" />}
      </button>

      {hasChildren && childPositions.map((c, i) =>
      <button
        key={c.id}
        type="button"
        className="rz-slot rz-slot--child"
        style={{
          left: half + c.dx,
          top: half + c.dy,
          width: CHILD_SLOT + 6,
          height: CHILD_SLOT + 30,
          transitionDelay: `${i * 40}ms`
        }}
        onMouseEnter={() => onRequestOpen(slot.id)}
        onMouseLeave={() => onRequestClose(slot.id)}
        onClick={(e) => {e.stopPropagation();onPick(c);}}
        tabIndex={isOpen ? 0 : -1}>
        
          <span className="rz-slot-disc rz-slot-disc--child" style={{ width: CHILD_SLOT, height: CHILD_SLOT }}>
            <img src={getRes(c.res)} alt="" draggable="false" />
          </span>
          <span className="rz-slot-label rz-slot-label--child">{c.name}</span>
        </button>
      )}
    </div>);

};

// =============================================================================
// Floating active-brush label — text that appears at the top-left of the
// canvas, fades in fresh on every brush change, drifts up slightly.
// =============================================================================
const ActiveBrushLabel = ({ brush, flash }) =>
<div
  className="rz-active-label"
  /* Re-mount on every brush change so the entrance animation re-runs */
  key={brush.id + (flash ? '-flash' : '')}>
  
    <div className="rz-active-eyebrow">ACTIVE BRUSH</div>
    <div className="rz-active-name">{brush.name}</div>
    <div className={`rz-active-status ${flash ? 'is-loaded' : ''}`}>
      <span className="rz-status-dot" />
      {flash ? 'loaded via bridge' : 'standing by'}
    </div>
  </div>;


// =============================================================================
// Demo section
// =============================================================================
const Demo = () => {
  const sectionRef = useRefD(null);
  const canvasRef = useRefD(null);

  const splineReady = useLazySplineLoader(sectionRef);

  const [menu, setMenu] = useStateD(null);
  const [activeBrush, setActiveBrush] = useStateD(DEMO_BRUSHES[0]);
  const [flash, setFlash] = useStateD(false);
  const [hasInteracted, setHasInteracted] = useStateD(false);

  const [canvasSize, setCanvasSize] = useStateD({ width: 0, height: 0 });
  useEffectD(() => {
    const update = () => {
      const c = canvasRef.current;
      if (!c) return;
      const r = c.getBoundingClientRect();
      setCanvasSize({ width: r.width, height: r.height });
    };
    update();
    window.addEventListener('resize', update);
    const ro = new ResizeObserver(update);
    if (canvasRef.current) ro.observe(canvasRef.current);
    return () => {window.removeEventListener('resize', update);ro.disconnect();};
  }, []);

  const onCanvasClick = useCallbackD((e) => {
    const c = canvasRef.current;
    if (!c) return;
    const r = c.getBoundingClientRect();
    const x = e.clientX - r.left;
    const y = e.clientY - r.top;
    setHasInteracted(true);
    setMenu((cur) => cur ? null : { x, y });
  }, []);

  const pickBrush = useCallbackD((b) => {
    setActiveBrush(b);
    setMenu(null);
    setFlash(true);
    window.clearTimeout(pickBrush._t);
    pickBrush._t = window.setTimeout(() => setFlash(false), 1600);
  }, []);

  const cancelMenu = useCallbackD(() => setMenu(null), []);

  useEffectD(() => {
    if (!menu) return;
    const onKey = (e) => {if (e.key === 'Escape') setMenu(null);};
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [menu]);

  return (
    <section className="demo-wrap" id="try" data-screen-label="02 The workflow" ref={sectionRef}>
      <div className="section-head demo-head">
        <div>
          <div className="lead">The workflow</div>
          <h2>One hotkey, all your brushes. <span className="it">Stay in the flow.</span></h2>
        </div>
        <div className="desc">
          RadialZ puts your entire brush library one hotkey away,
          floating over ZBrush exactly where you need it, gone the moment you don't.
        </div>
      </div>

      <div className="demo-stage">
        <ZBrushWireframe activeBrush={activeBrush} flashing={flash} />

        <div className="zb-canvas" ref={canvasRef} onClick={onCanvasClick}>
          <div className="zb-canvas-fallback" aria-hidden="true" />

          {splineReady &&
          <spline-viewer
            url="https://prod.spline.design/DwyzRGZdDkxM2TKX/scene.splinecode"
            loading-anim-type="none"
            events-target="global"
            style={{
              position: 'absolute', inset: 0,
              width: '100%', height: '100%',
              pointerEvents: 'none',
              background: 'transparent'
            }} />

          }

          {/* Floating active-brush text inside the canvas — fades in on update */}
          <ActiveBrushLabel brush={activeBrush} flash={flash} />

          {!hasInteracted &&
          <div className="rz-hint">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M4 4 L4 16 L8 13 L11 19 L13 18 L10 12 L15 12 Z" />
              </svg>
              <span>Click the canvas to summon RadialZ</span>
            </div>
          }

          {menu &&
          <RadialOverlay
            x={menu.x} y={menu.y}
            canvasRect={canvasSize}
            onPick={pickBrush}
            onCancel={cancelMenu} />

          }
        </div>
      </div>

      <p className="demo-honesty" style={{ fontFamily: "Poppins", fontSize: "15px" }}>
        A simple browser demo of how RadialZ works — the real plugin lives inside ZBrush,
        loads brushes through the Bridge, and is faster than this preview lets on.
      </p>
    </section>);

};

window.Demo = Demo;