/* global React */
// Character-by-character reveal — every char is laid out from the start
// (full-text width reserved), but starts invisible and fades up with a small
// stagger so the headline still feels "typed in" without any reflow.
//
// Chars are grouped into per-word inline-block wrappers so the browser only
// breaks lines at spaces — without this, an `inline-block` per char lets
// text-wrap: balance + max-width split words mid-letter ("cer / to" bug).
const { useEffect, useState, useMemo } = React;

function Typewriter({
  children,
  speed = 26,         // ms between chars
  startDelay = 0,
  as: Tag = "span",
  className,
  trigger = true,
  ...rest
}) {
  const text = children ?? "";

  // Bump this on every (text, trigger) change so we can restart animations.
  const stamp = useMemo(() => Date.now(), [text, trigger]);

  const nodes = useMemo(() => {
    // Walk char-by-char while emitting word-wrappers between spaces so lines
    // can only break at whitespace. Each char inside a word still animates
    // with its own staggered delay.
    const out = [];
    const words = text.split(" ");
    let cIdx = 0;
    words.forEach((word, wIdx) => {
      if (wIdx > 0) out.push(" "); // plain space text node — break point
      const chars = [];
      for (let i = 0; i < word.length; i++) {
        const ch = word[i];
        chars.push(
          <span
            key={`${stamp}-${wIdx}-${i}`}
            className="tw-c"
            style={{ animationDelay: `${startDelay + cIdx * speed}ms` }}
          >
            {ch}
          </span>
        );
        cIdx++;
      }
      out.push(
        <span key={`${stamp}-w-${wIdx}`} className="tw-w">{chars}</span>
      );
    });
    return out;
  }, [text, stamp, speed, startDelay]);

  if (!trigger) {
    return <Tag className={className} {...rest}>{text}</Tag>;
  }
  return <Tag className={className} {...rest}>{nodes}</Tag>;
}

// Simple fade-in wrapper used for the soft headline line.
function FadeIn({ children, delay = 0, as: Tag = "span", className, ...rest }) {
  const [on, setOn] = useState(false);
  useEffect(() => {
    setOn(false);
    const id = setTimeout(() => setOn(true), delay);
    return () => clearTimeout(id);
  }, [delay, children]);
  return (
    <Tag className={`${className || ""} fade-in ${on ? "fade-in-on" : ""}`} {...rest}>
      {children}
    </Tag>
  );
}

window.Typewriter = Typewriter;
window.FadeIn = FadeIn;
