// LumenBackdrop.jsx — live LUMEN surfaces (heroes, bands, prose tiles)

(function () {
  var LUMEN_SLOT = null;
  var LUMEN_CANDIDATES = new Map();

  function electLumenSlot() {
    var bestId = null;
    var bestScore = -1;
    LUMEN_CANDIDATES.forEach(function (c, id) {
      if (c.ratio < 0.02) return;
      var score = c.ratio * 1000;
      if (c.variant === 'hero') score += 800;
      if (score > bestScore) {
        bestScore = score;
        bestId = id;
      }
    });

    if (!bestId) {
      if (LUMEN_SLOT) {
        var prev = LUMEN_CANDIDATES.get(LUMEN_SLOT.id);
        if (prev && prev.onRevoked) prev.onRevoked();
        LUMEN_SLOT.destroy();
        LUMEN_SLOT = null;
      }
      return;
    }

    if (LUMEN_SLOT && LUMEN_SLOT.id === bestId) return;

    if (LUMEN_SLOT) {
      var old = LUMEN_CANDIDATES.get(LUMEN_SLOT.id);
      if (old && old.onRevoked) old.onRevoked();
      LUMEN_SLOT.destroy();
      LUMEN_SLOT = null;
    }

    var pick = LUMEN_CANDIDATES.get(bestId);
    var engine = createLumenEngine(pick.canvas, pick.getParams, pick.opts);
    LUMEN_SLOT = {
      id: bestId,
      destroy: function () {
        engine.destroy();
        if (LUMEN_SLOT && LUMEN_SLOT.id === bestId) LUMEN_SLOT = null;
      },
    };
    if (pick.onGranted) pick.onGranted(engine);
  }

  function registerCandidate(id, meta) {
    LUMEN_CANDIDATES.set(id, meta);
    electLumenSlot();
  }

  function unregisterCandidate(id) {
    LUMEN_CANDIDATES.delete(id);
    if (LUMEN_SLOT && LUMEN_SLOT.id === id) {
      LUMEN_SLOT.destroy();
      LUMEN_SLOT = null;
    }
    electLumenSlot();
  }

  function updateCandidateRatio(id, ratio) {
    var c = LUMEN_CANDIDATES.get(id);
    if (!c) return;
    c.ratio = ratio;
    electLumenSlot();
  }

  function useLumenSurface(rootRef, slug, variant, animate) {
    var useLive = animate !== false
      && typeof lumenLiveAllowed === 'function'
      && lumenLiveAllowed()
      && typeof createLumenEngine === 'function'
      && typeof lumenParamsFromSlug === 'function';

    var surfaceIdRef = React.useRef(slug + ':' + variant + ':' + Math.random().toString(36).slice(2, 9));
    var canvasRef = React.useRef(null);
    var engineRef = React.useRef(null);
    var paramsRef = React.useRef(null);
    var ratioRef = React.useRef(0);
    var inViewRef = React.useRef(false);
    var [live, setLive] = React.useState(false);
    var [failed, setFailed] = React.useState(false);
    var [inView, setInView] = React.useState(false);

    React.useEffect(function () {
      if (!useLive || !rootRef.current) return undefined;
      if (variant === 'hero') {
        inViewRef.current = true;
        setInView(true);
        ratioRef.current = 1;
        updateCandidateRatio(surfaceIdRef.current, 1);
      }
      var obs = new IntersectionObserver(function (entries) {
        entries.forEach(function (e) {
          if (e.target !== rootRef.current) return;
          ratioRef.current = e.intersectionRatio;
          var next = variant === 'hero'
            ? e.intersectionRatio > 0.01
            : (inViewRef.current
              ? e.intersectionRatio > 0.02
              : e.intersectionRatio >= 0.06);
          if (next !== inViewRef.current) {
            inViewRef.current = next;
            setInView(next);
          }
          updateCandidateRatio(surfaceIdRef.current, e.intersectionRatio);
        });
      }, { threshold: [0, 0.02, 0.06, 0.08, 0.15, 0.35, 0.55, 0.75] });
      obs.observe(rootRef.current);
      return function () {
        obs.disconnect();
        inViewRef.current = false;
        ratioRef.current = 0;
        setInView(false);
        updateCandidateRatio(surfaceIdRef.current, 0);
      };
    }, [useLive, rootRef, variant]);

    React.useEffect(function () {
      var surfaceId = surfaceIdRef.current;
      if (!useLive || !inView || !canvasRef.current) {
        unregisterCandidate(surfaceId);
        engineRef.current = null;
        setLive(false);
        return undefined;
      }

      var cancelled = false;
      var P = lumenParamsFromSlug(slug, variant);
      if (!P) {
        setFailed(true);
        return undefined;
      }
      paramsRef.current = P;
      setFailed(false);

      registerCandidate(surfaceId, {
        canvas: canvasRef.current,
        getParams: function () { return paramsRef.current; },
        ratio: ratioRef.current,
        variant: variant,
        opts: {
          maxFps: 30,
          onError: function () {
            if (!cancelled) { setFailed(true); setLive(false); }
          },
          onReady: function () {
            if (!cancelled && LUMEN_SLOT && LUMEN_SLOT.id === surfaceId) setLive(true);
          },
        },
        onGranted: function (engine) {
          if (cancelled) return;
          engineRef.current = engine;
        },
        onRevoked: function () {
          if (cancelled) return;
          engineRef.current = null;
          setLive(false);
        },
      });

      return function () {
        cancelled = true;
        unregisterCandidate(surfaceId);
        engineRef.current = null;
        setLive(false);
      };
    }, [useLive, inView, slug, variant]);

    var arming = useLive && inView && !live && !failed;
    return { canvasRef: canvasRef, live: live, arming: arming, failed: failed, useLive: useLive };
  }

  function useLumenTile(rootRef, slug, animate) {
    var useLive = animate !== false
      && typeof lumenLiveAllowed === 'function'
      && lumenLiveAllowed()
      && typeof createLumenEngine === 'function'
      && typeof lumenParamsFromSlug === 'function';

    var canvasRef = React.useRef(null);
    var engineRef = React.useRef(null);
    var paramsRef = React.useRef(null);
    var inViewRef = React.useRef(false);
    var [ready, setReady] = React.useState(false);
    var [failed, setFailed] = React.useState(false);
    var [inView, setInView] = React.useState(false);

    React.useEffect(function () {
      if (!useLive || !rootRef.current) return undefined;
      var obs = new IntersectionObserver(function (entries) {
        entries.forEach(function (e) {
          if (e.target !== rootRef.current) return;
          var next = inViewRef.current
            ? e.intersectionRatio > 0.02
            : e.intersectionRatio >= 0.08;
          if (next !== inViewRef.current) {
            inViewRef.current = next;
            setInView(next);
          }
        });
      }, { threshold: [0, 0.02, 0.06, 0.08, 0.15, 0.35, 0.55] });
      obs.observe(rootRef.current);
      return function () {
        obs.disconnect();
        inViewRef.current = false;
        setInView(false);
      };
    }, [useLive, rootRef]);

    React.useEffect(function () {
      if (!useLive || !inView || !canvasRef.current) {
        if (engineRef.current) {
          engineRef.current.destroy();
          engineRef.current = null;
        }
        setReady(false);
        return undefined;
      }

      var cancelled = false;
      var P = lumenParamsFromSlug(slug, 'tile');
      if (!P) {
        setFailed(true);
        return undefined;
      }
      paramsRef.current = P;
      setFailed(false);
      setReady(false);

      var startId = window.setTimeout(function () {
        if (cancelled || !canvasRef.current) return;
        var engine = createLumenEngine(canvasRef.current, function () { return paramsRef.current; }, {
          maxFps: 30,
          onError: function () {
            if (!cancelled) { setFailed(true); setReady(false); }
          },
          onReady: function () {
            if (!cancelled) setReady(true);
          },
        });
        engineRef.current = engine;
      }, 0);

      return function () {
        cancelled = true;
        window.clearTimeout(startId);
        if (engineRef.current) {
          engineRef.current.destroy();
          engineRef.current = null;
        }
        setReady(false);
      };
    }, [useLive, inView, slug]);

    var arming = useLive && inView && !ready && !failed;
    return { canvasRef: canvasRef, ready: ready, arming: arming, failed: failed, useLive: useLive };
  }

  Object.assign(window, {
    DsBackdropSection: function DsBackdropSection({ slug, variant, className, style, children, animate }) {
      const t = darkTheme;
      const rootRef = React.useRef(null);
      var v = variant || 'hero';
      var surface = useLumenSurface(rootRef, slug, v, animate);

      var scrimClass = 'ds-backdrop-scrim ds-backdrop-scrim--' + v;
      var staticStyle = surface.useLive && !surface.failed
        ? dsBackdropPoster(slug)
        : dsBackdrop(slug, v);
      var sectionStyle = Object.assign({
        position: 'relative',
        overflow: 'hidden',
        backgroundColor: t.bg,
      }, staticStyle, style || {});

      var sectionClass = (className || '')
        + (surface.arming ? ' ds-backdrop-section--arming' : '')
        + (surface.live ? ' ds-backdrop-section--live' : '');

      return (
        <section
          ref={rootRef}
          className={sectionClass}
          style={sectionStyle}
          data-backdrop-slug={slug}
          data-backdrop-variant={v}
        >
          {surface.useLive && !surface.failed ? (
            <canvas
              ref={surface.canvasRef}
              className={'ds-lumen-canvas' + (surface.live ? ' ds-lumen-canvas--ready' : '')}
              aria-hidden="true"
            />
          ) : null}
          {surface.useLive && !surface.failed ? (
            <div className={scrimClass} aria-hidden="true" />
          ) : null}
          <div className="ds-backdrop-content">
            {children}
          </div>
        </section>
      );
    },

    DsLumenTile: function DsLumenTile({ slug, animate }) {
      const rootRef = React.useRef(null);
      var surface = useLumenTile(rootRef, slug, animate);
      var tileStyle = surface.useLive && !surface.failed && typeof dsBackdropPoster === 'function'
        ? dsBackdropPoster(slug)
        : (typeof dsBackdrop === 'function'
          ? dsBackdrop(slug, 'tile')
          : { backgroundColor: darkTheme.bg });

      return (
        <div
          ref={rootRef}
          className={'ds-lumen-tile'
            + (surface.arming ? ' ds-lumen-tile--arming' : '')
            + (surface.ready ? ' ds-lumen-tile--live' : '')}
          data-backdrop-slug={slug}
          style={tileStyle}
        >
          {surface.useLive && !surface.failed ? (
            <canvas
              ref={surface.canvasRef}
              className={'ds-lumen-canvas' + (surface.ready ? ' ds-lumen-canvas--ready' : '')}
              aria-hidden="true"
            />
          ) : null}
        </div>
      );
    },
  });
})();
