/* global React, BrushIcon, RadialMenuSVG */
const { useState: useState2, useEffect: useEffect2, useRef: useRef2 } = React;

// Features attached to specific brushes.
// - hoverImage: shown while hovering (single still frame)
// - frames: optional array — played as an animation on click, settles on last frame
// Add more entries here as the user provides graphics for other brushes.
const REVEAL_FEATURES = {
  top: {
    label: 'Child brushes',
    hoverImage: window.__resources['reveal-children01'],
    expandImage: window.__resources['reveal-children02'],
    callout: {
      title: 'Nested brush groups',
      body: 'Each slot can hold a primary brush PLUS up to 3 children. Click to expand, flick to pick.',
      hint: 'Click the highlighted brush to expand'
    }
  },
  'top-right': {
    label: 'Swap any brush',
    hoverImage: window.__resources['polish-01'],
    frames: Array.from({ length: 15 }, (_, i) => window.__resources['polish-' + String(i + 1).padStart(2, '0')]),
    frameDuration: 55,
    callout: {
      title: 'Swap any slot, instantly',
      body: "Drop a different brush into any position. The new brush takes over the slot, no rebinding.",
      hint: 'Click to watch the swap'
    }
  },
  'right': {
    label: 'Custom icons',
    hoverImage: window.__resources['icon-00'],
    expandImage: window.__resources['icon-01'],
    callout: {
      title: 'Custom icons & shortcuts',
      body: "Upload your own icons for any slot, or swap a brush for any ZBrush shortcut you've assigned. Make the menu yours.",
      hint: 'Click to see a custom icon in action'
    }
  }
};

const Reveal = ({ scrollY, sectionTop, vh }) => {
  const sectionHeight = vh * 2.0;
  // Reveal completes shortly AFTER the section becomes sticky, so the user
  // can briefly see the OFF state when the section first enters view.
  const leadIn = vh * 0.35;
  const revealOver = vh * 0.85;
  const localScroll = scrollY - sectionTop + leadIn;
  const p = Math.max(0, Math.min(1, localScroll / revealOver));

  // Interaction state
  const [hoveredId, setHoveredId] = useState2(null);
  const [activeId, setActiveId] = useState2(null);
  const [animFrame, setAnimFrame] = useState2(0);
  const animTimerRef = useRef2(null);

  // Brush hotspot positions
  const defaultHotspots = [
  { id: 'top', x: 50.80, y: 38.50, label: 'Move' },
  { id: 'top-right', x: 63.50, y: 40.00, label: 'Polish' },
  { id: 'right', x: 68.65, y: 53.00, label: 'TrimDynamic' },
  { id: 'bottom-right', x: 64.43, y: 63.25, label: 'DamStandard' },
  { id: 'bottom', x: 51.04, y: 67.50, label: 'hPolish' },
  { id: 'bottom-left', x: 40.97, y: 63.25, label: 'Inflate' },
  { id: 'left', x: 36.27, y: 53.00, label: 'Pinch' },
  { id: 'top-left', x: 39.84, y: 42.75, label: 'SnakeHook' }];


  // Calibration mode
  const calMode = typeof window !== 'undefined' && new URLSearchParams(window.location.search).get('cal') === '1';
  const [brushHotspots, setBrushHotspots] = useState2(defaultHotspots);
  const stageRef = useRef2(null);

  const handleDrag = (id, e) => {
    if (!calMode || !stageRef.current) return;
    const rect = stageRef.current.getBoundingClientRect();
    const x = (e.clientX - rect.left) / rect.width * 100;
    const y = (e.clientY - rect.top) / rect.height * 100;
    setBrushHotspots((arr) => arr.map((h) => h.id === id ? { ...h, x: +x.toFixed(2), y: +y.toFixed(2) } : h));
  };

  const dumpPositions = () => {
    const out = brushHotspots.map((h) => `    { id: '${h.id}', x: ${h.x.toFixed(2)}, y: ${h.y.toFixed(2)}, label: '${h.label}' },`).join('\n');
    console.log('// Paste into reveal.jsx defaultHotspots:\n' + out);
    if (navigator.clipboard) navigator.clipboard.writeText(out);
    alert('Positions logged to console and copied to clipboard.');
  };

  // Reveal mask
  const reveal = Math.max(0, Math.min(1, p));
  const r = reveal * 130;
  const feather = 28;
  const innerR = Math.max(0, r - feather);
  const revealMask = `radial-gradient(circle at 50% 55%, black ${innerR}%, transparent ${r}%)`;
  const onOpacity = Math.min(1, reveal * 1.4);

  // Hotspots become interactive once the reveal is mostly complete
  const interactive = reveal >= 0.7;

  // Animation playback
  useEffect2(() => {
    if (animTimerRef.current) {clearTimeout(animTimerRef.current);animTimerRef.current = null;}
    const feature = activeId && REVEAL_FEATURES[activeId];
    if (!feature || !feature.frames) {setAnimFrame(0);return;}
    setAnimFrame(0);
    let i = 0;
    const total = feature.frames.length;
    const dur = feature.frameDuration || 60;
    const tick = () => {
      i++;
      if (i >= total) {setAnimFrame(total - 1);return;}
      setAnimFrame(i);
      animTimerRef.current = setTimeout(tick, dur);
    };
    animTimerRef.current = setTimeout(tick, dur);
    return () => {if (animTimerRef.current) clearTimeout(animTimerRef.current);};
  }, [activeId]);

  // Preload polish frames
  useEffect2(() => {
    const f = REVEAL_FEATURES['top-right']?.frames || [];
    f.forEach((src) => {const img = new Image();img.src = src;});
  }, []);

  // Layer visibility
  const topExpand = activeId === 'top' ? REVEAL_FEATURES.top.expandImage : null;
  const topHover = !activeId && hoveredId === 'top' ? REVEAL_FEATURES.top.hoverImage : null;
  const trAnimSrc = activeId === 'top-right' ? REVEAL_FEATURES['top-right'].frames[animFrame] : null;
  const trHoverSrc = !activeId && hoveredId === 'top-right' ? REVEAL_FEATURES['top-right'].hoverImage : null;
  const rightExpand = activeId === 'right' ? REVEAL_FEATURES.right.expandImage : null;
  const rightHover = !activeId && hoveredId === 'right' ? REVEAL_FEATURES.right.hoverImage : null;

  const handleStageClick = (e) => {
    if (e.target.closest('.reveal-hotspot')) return;
    setActiveId(null);
  };

  const callout = activeId && REVEAL_FEATURES[activeId]?.callout ||
  hoveredId && REVEAL_FEATURES[hoveredId]?.callout ||
  null;
  const calloutNum = activeId === 'top' || hoveredId === 'top' ? '01' :
  activeId === 'top-right' || hoveredId === 'top-right' ? '02' : '01';

  return (
    <section className="reveal-wrap" data-screen-label="02 ZBrush Reveal">
      <div className="reveal-sticky">
        <div className="reveal-header">
          <div className="reveal-tagline">The workflow</div>
          <h2 className="reveal-h2">
            One hotkey, all your brushes. <span className="orange-it">Stay in the flow.</span>
          </h2>
        </div>

        <div className="reveal-stage" onClick={handleStageClick} ref={stageRef}>
          {calMode &&
          <div className="reveal-cal-toolbar">
              <span>CAL MODE · drag the rings to align with brushes</span>
              <button onClick={dumpPositions}>Copy positions</button>
            </div>
          }

          <img className="reveal-img reveal-off" src={window.__resources['reveal-off']} alt="" draggable={false} />
          <img
            className="reveal-img reveal-on"
            src={window.__resources['reveal-on']}
            alt=""
            draggable={false}
            style={{
              WebkitMaskImage: revealMask,
              maskImage: revealMask,
              opacity: onOpacity
            }} />
          

          {/* Top brush hover/expand */}
          <img className="reveal-img reveal-layer-hover" src={REVEAL_FEATURES.top.hoverImage} alt="" draggable={false} style={{ opacity: topHover ? 1 : 0 }} />
          <img className="reveal-img reveal-layer-expand" src={REVEAL_FEATURES.top.expandImage} alt="" draggable={false} style={{ opacity: topExpand ? 1 : 0 }} />

          {/* Top-right brush hover + animated frames (opacity-swap for smooth playback) */}
          {trHoverSrc &&
          <img className="reveal-img reveal-layer-hover" src={trHoverSrc} alt="" draggable={false} style={{ opacity: 1 }} />
          }
          {/* All 15 polish frames are always in the DOM (preloaded + GPU-cached); only one has opacity 1 at a time */}
          {REVEAL_FEATURES['top-right'].frames.map((src, i) =>
          <img
            key={src}
            className="reveal-img reveal-layer-anim"
            src={src}
            alt=""
            draggable={false}
            style={{ opacity: activeId === 'top-right' && animFrame === i ? 1 : 0 }} />

          )}

          {/* Right brush hover/expand (custom icons) */}
          <img className="reveal-img reveal-layer-hover" src={REVEAL_FEATURES.right.hoverImage} alt="" draggable={false} style={{ opacity: rightHover ? 1 : 0 }} />
          <img className="reveal-img reveal-layer-expand" src={REVEAL_FEATURES.right.expandImage} alt="" draggable={false} style={{ opacity: rightExpand ? 1 : 0 }} />


          {(interactive || calMode) &&
          <div className="reveal-hotspots">
              {brushHotspots.map((h) =>
            <BrushHotspot
              key={h.id}
              {...h}
              hasFeature={!!REVEAL_FEATURES[h.id]}
              isActive={activeId === h.id}
              isHovered={hoveredId === h.id}
              calMode={calMode}
              onDrag={(e) => handleDrag(h.id, e)}
              onEnter={() => setHoveredId(h.id)}
              onLeave={() => setHoveredId(null)}
              onClick={(e) => {
                e.stopPropagation();
                if (REVEAL_FEATURES[h.id]) {
                  setActiveId(activeId === h.id ? null : h.id);
                }
              }} />

            )}
            </div>
          }

          {interactive && callout &&
          <div className={`reveal-callout ${activeId ? 'active' : 'preview'}`}>
              <div className="callout-title">{callout.title}</div>
              <div className="callout-body">{callout.body}</div>
              {!activeId &&
            <div className="callout-hint">↳ {callout.hint}</div>
            }
              {activeId &&
            <button className="callout-close" onClick={(e) => {e.stopPropagation();setActiveId(null);}}>
                  Collapse ×
                </button>
            }
            </div>
          }
        </div>

        <div className="reveal-copy">
          <p>RadialZ puts your entire brush library one hotkey away, floating over ZBrush exactly where you need it, gone the moment you don't.</p>
        </div>
      </div>
    </section>);

};

// Hotspot
const BrushHotspot = ({ x, y, label, id, hasFeature, isActive, isHovered, onEnter, onLeave, onClick, calMode, onDrag }) => {
  const dragging = useRef2(false);
  const startDrag = (e) => {
    if (!calMode) return;
    e.stopPropagation();
    e.preventDefault();
    dragging.current = true;
    const move = (ev) => {if (dragging.current) onDrag(ev);};
    const up = () => {
      dragging.current = false;
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
    };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
  };
  return (
    <div
      className={`reveal-hotspot ${isActive ? 'active' : ''} ${isHovered ? 'hovered' : ''} ${hasFeature ? 'has-feature' : ''} ${calMode ? 'cal-mode' : ''}`}
      style={{ left: `${x}%`, top: `${y}%` }}
      onMouseEnter={!calMode ? onEnter : undefined}
      onMouseLeave={!calMode ? onLeave : undefined}
      onMouseDown={calMode ? startDrag : undefined}
      onClick={!calMode ? onClick : undefined}>
      
      <div className="hotspot-ring" />
      {calMode &&
      <div className="hotspot-cal-label">{id}<br />{x.toFixed(2)}, {y.toFixed(2)}</div>
      }
      {hasFeature && !isActive && !calMode &&
      <div className="hotspot-label">{label}<span className="hotspot-cta">click to expand</span></div>
      }
    </div>);

};

// Demo video section: the warm "See RadialZ in action." card with the framed
// sculpt video. A scroll-driven circular reveal masks the warm card in as the
// user scrolls into the section, recreating the "iris-open" wipe that used to
// connect the workflow section to the video.
const Transition = () => {
  const wrapRef = useRef2(null);
  const [reveal, setReveal] = useState2(0);

  useEffect2(() => {
    const el = wrapRef.current;
    if (!el) return;
    let raf = 0;
    const tick = () => {
      raf = 0;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || 800;
      // Reveal progress: starts when section is 70% into viewport (top still
      // below center), completes when section top reaches the viewport top.
      const start = vh * 0.70;
      const end = 0;
      const p = 1 - Math.max(0, Math.min(1, (r.top - end) / (start - end)));
      setReveal(p);
    };
    const onScroll = () => {if (!raf) raf = requestAnimationFrame(tick);};
    tick();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      if (raf) cancelAnimationFrame(raf);
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, []);

  // Map reveal (0→1) to mask radii. innerR is the fully-opaque center, outerR
  // is where the mask fades out — the gap between them is the feather edge.
  const outerR = reveal * 130;
  const feather = 28;
  const innerR = Math.max(0, outerR - feather);
  const styleVars = {
    '--rz-rev-inner': `${innerR}%`,
    '--rz-rev-outer': `${outerR}%`
  };

  return (
    <section className="transition-wrap has-reveal" id="demo" data-screen-label="03 Demo" ref={wrapRef}>
      {/* Dark→warm dome: a shallow warm arc bulges UP into the dark Demo
          section above, marking the boundary. Lives outside the sticky child
          so it scrolls naturally with the section start. Kept shallow so it
          doesn't cover the demo's disclaimer line. */}
      <svg
        className="transition-top-dome"
        viewBox="0 0 1440 240"
        preserveAspectRatio="none"
        aria-hidden="true"
      >
        <path d="M0,240 Q720,-60 1440,240 Z" fill="#ede7da" />
      </svg>

      <div className="transition-sticky">
        <div className="demo-base" style={styleVars}>
          <div className="demo-inner">
            <h2 className="demo-h2">
              See <span className="orange-it">RadialZ in action.</span>
            </h2>
            <DemoFrame />
            <div className="demo-sub">Here is a quick video using RadialZ in a real sculpting session.

            </div>
          </div>
        </div>
      </div>
    </section>);

};

// Framed demo video with a play overlay
const DemoFrame = () => {
  const ref = useRef2(null);
  const [playing, setPlaying] = useState2(false);
  const togglePlay = () => {
    const v = ref.current;
    if (!v) return;
    if (v.paused) {v.play();setPlaying(true);} else
    {v.pause();setPlaying(false);}
  };
  return (
    <div className="demo-frame" onClick={togglePlay}>
      <video
        ref={ref}
        className="demo-video"
        src={window.__resources['sculpt-bg']}
        playsInline
        preload="metadata"
        onPlay={() => setPlaying(true)}
        onPause={() => setPlaying(false)}
        onEnded={() => setPlaying(false)} />
      
      <div className={`demo-play ${playing ? 'playing' : ''}`}>
        {playing ?
        <svg width="22" height="22" viewBox="0 0 24 24"><rect x="6" y="5" width="4" height="14" fill="currentColor" /><rect x="14" y="5" width="4" height="14" fill="currentColor" /></svg> :

        <svg width="22" height="22" viewBox="0 0 24 24"><path d="M7 4 L19 12 L7 20 Z" fill="currentColor" /></svg>
        }
      </div>
    </div>);

};

window.Reveal = Reveal;
window.Transition = Transition;