/* global React */
/* Interactive "bending line" — drag the cursor through it and the hairline
   flexes, then springs back. Sits in the existing gap between sections with
   ~0 layout height so it never changes the spacing around it. */
const { useRef: useWaveRef, useEffect: useWaveEffect } = React;

function WavePath({ className }) {
  const wrap = useWaveRef(null);
  const path = useWaveRef(null);
  const s = useWaveRef({ progress: 0, x: 0.5, time: Math.PI / 2, reqId: null });

  const widthOf = () =>
    (wrap.current ? wrap.current.getBoundingClientRect().width : window.innerWidth * 0.7);

  const setPath = (progress) => {
    const p = path.current;
    if (!p) return;
    const w = widthOf();
    p.setAttributeNS(null, "d", `M0 100 Q${w * s.current.x} ${100 + progress * 0.6}, ${w} 100`);
  };

  useWaveEffect(() => {
    setPath(0);
    const onResize = () => setPath(s.current.progress);
    window.addEventListener("resize", onResize);
    return () => {
      window.removeEventListener("resize", onResize);
      if (s.current.reqId) cancelAnimationFrame(s.current.reqId);
    };
  }, []);

  const lerp = (a, b, t) => a * (1 - t) + b * t;

  const resetAnim = () => {
    s.current.time = Math.PI / 2;
    s.current.progress = 0;
  };

  const animateOut = () => {
    const st = s.current;
    const newProgress = st.progress * Math.sin(st.time);
    st.progress = lerp(st.progress, 0, 0.025);
    st.time += 0.2;
    setPath(newProgress);
    if (Math.abs(st.progress) > 0.75) {
      st.reqId = requestAnimationFrame(animateOut);
    } else {
      resetAnim();
    }
  };

  const onEnter = () => {
    const st = s.current;
    if (st.reqId) {
      cancelAnimationFrame(st.reqId);
      st.reqId = null;
      resetAnim();
    }
  };

  const onMove = (e) => {
    const st = s.current;
    const b = e.currentTarget.getBoundingClientRect();
    st.x = Math.max(0, Math.min(1, (e.clientX - b.left) / b.width));
    st.progress += e.movementY;
    setPath(st.progress);
  };

  const onLeave = () => animateOut();

  return (
    <div ref={wrap} className={"wave-path" + (className ? " " + className : "")} aria-hidden="true">
      <div className="wave-hit" onMouseEnter={onEnter} onMouseMove={onMove} onMouseLeave={onLeave} />
      <svg className="wave-svg"><path ref={path} /></svg>
    </div>
  );
}

Object.assign(window, { WavePath });
