/* @jsx React.createElement */
/* Shared utilities — scramble hook, live clock hook, formatters. */

const { useState: useStateU, useEffect: useEffectU, useRef: useRefU } = React;

const SCRAMBLE_CHARS = "0123456789ABCDEF#%/-";

/**
 * Scramble a string to a target. Cycles random mono chars for ~400ms / 8 frames
 * before settling. Per the brand's one motion signature.
 */
function useScramble(target, deps = []) {
  const [out, setOut] = useStateU(target);
  const [scrambling, setScrambling] = useStateU(false);
  const rafRef = useRefU(null);
  useEffectU(() => {
    setScrambling(true);
    const t0 = performance.now();
    const dur = 400;
    const tick = (now) => {
      const p = Math.min(1, (now - t0) / dur);
      // gradually reveal characters left-to-right
      const reveal = Math.floor(p * target.length);
      let s = "";
      for (let i = 0; i < target.length; i++) {
        if (i < reveal || /[\s.:·\-/]/.test(target[i])) {
          s += target[i];
        } else {
          s += SCRAMBLE_CHARS[Math.floor(Math.random() * SCRAMBLE_CHARS.length)];
        }
      }
      setOut(s);
      if (p < 1) {
        rafRef.current = requestAnimationFrame(tick);
      } else {
        setOut(target);
        setScrambling(false);
      }
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
    // eslint-disable-next-line
  }, deps);
  return [out, scrambling];
}

function Scramble({ value, className = "", style }) {
  const [out, scrambling] = useScramble(value, [value]);
  return (
    <span
      className={"vc-scramble " + (scrambling ? "is-scrambling " : "") + className}
      style={style}
    >
      {out}
    </span>
  );
}

/** Live UTC clock — updates every second, returns "1438Z" / date strings. */
function useUTCClock() {
  const [now, setNow] = useStateU(() => new Date());
  useEffectU(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const hh = String(now.getUTCHours()).padStart(2, "0");
  const mm = String(now.getUTCMinutes()).padStart(2, "0");
  const ss = String(now.getUTCSeconds()).padStart(2, "0");
  return {
    z: `${hh}${mm}Z`,
    full: `${hh}:${mm}:${ss}Z`,
    dateCode: `${String(now.getUTCFullYear()).slice(2)}·${String(now.getUTCMonth() + 1).padStart(2, "0")}·${String(now.getUTCDate()).padStart(2, "0")}`,
    iso: now.toISOString(),
  };
}

/** Animate a number from 0 to target on mount. Eases out. */
function useCounter(target, durationMs = 1200) {
  const [v, setV] = useStateU(0);
  useEffectU(() => {
    const t0 = performance.now();
    let raf;
    const step = (now) => {
      const p = Math.min(1, (now - t0) / durationMs);
      const eased = 1 - Math.pow(1 - p, 3);
      setV(Math.round(eased * target));
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [target, durationMs]);
  return v;
}

/* Sparkline-ish bars for the readout — randomized once per "data refresh". */
function useBarSeries(n = 18, seed = 0) {
  const arr = [];
  let s = seed * 9301 + 49297;
  for (let i = 0; i < n; i++) {
    s = (s * 9301 + 49297) % 233280;
    arr.push(0.3 + (s / 233280) * 0.7);
  }
  return arr;
}

Object.assign(window, { useScramble, Scramble, useUTCClock, useCounter, useBarSeries });
