// v5 — Portfolio module: the znerold.co /work tile pattern on the homepage.
// Replaces the video slideshow (V5Showcase, still on disk, unmounted).
//
// Markup = /work's first six tiles (Kodak, Apple Music, Adobe, Target, Garden
// Variety, Outdoorsy), verbatim, generated into
// src/v5-portfolio-tiles.js by _tools/build_portfolio.py together with the scoped
// Squarespace theme CSS (src/v5-portfolio.css). The behaviours below are a port of
// the modules in /sqs/sqs-runtime.js that those blocks need: the fluid-image
// cover/contain math, autoplay guarantees for the tile videos, and the scroll-in
// "animation-loaded" state. (The scrolling-title marquee strip was removed.)

const V5_PF_REDUCED = !!(window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches);

const v5pfNum = (v, d) => { const n = parseFloat(v); return isNaN(n) ? d : n; };
const v5pfJson = (s, d) => { if (!s) return d; try { return JSON.parse(s); } catch (e) { return d; } };
const v5pfDebounce = (fn, ms) => { let t; return () => { clearTimeout(t); t = setTimeout(fn, ms); }; };
const v5pfInView = (el, cb, margin) => {
  if (!("IntersectionObserver" in window)) { cb(); return () => {}; }
  const io = new IntersectionObserver((es) => {
    es.forEach((e) => { if (e.isIntersecting) { io.unobserve(e.target); cb(); } });
  }, { rootMargin: margin || "0px 0px -5% 0px", threshold: 0 });
  io.observe(el);
  return () => io.disconnect();
};

/* ---------------------------------------------------------------- fluid image blocks (cover / contain math) */
function v5pfImgDims(img) {
  const d = (img.getAttribute("data-image-dimensions") || "").split("x");
  let w = v5pfNum(d[0], 0), h = v5pfNum(d[1], 0);
  if (!w || !h) { w = img.naturalWidth || v5pfNum(img.getAttribute("width"), 0); h = img.naturalHeight || v5pfNum(img.getAttribute("height"), 0); }
  return { w: w || 4, h: h || 3 };
}
function v5pfFitFluid(root) {
  const img = root.querySelector("img"); if (!img) return;
  const stretched = root.getAttribute("data-is-image-stretched") !== "false";
  const host = root.parentNode || root;
  if (stretched) {
    root.style.setProperty("--image-component-object-fit", "cover");
    root.style.setProperty("--image-component-container-height", "100%");
    root.style.setProperty("--image-component-container-width", "100%");
    return;
  }
  const d = v5pfImgDims(img), aspect = d.w / d.h;
  const W = host.clientWidth, H = host.clientHeight;
  if (!W || !H) return;
  root.classList.add("image-component-container-fit");
  root.style.setProperty("--image-component-object-fit", "contain");
  root.style.setProperty("--image-component-native-aspect-ratio", String(aspect));
  if (W / H > aspect) {
    root.style.setProperty("--image-component-container-height", "100%");
    root.style.setProperty("--image-component-container-width", (H * aspect) + "px");
  } else {
    root.style.setProperty("--image-component-container-width", "100%");
    root.style.setProperty("--image-component-container-height", (W / aspect) + "px");
  }
}

/* ---------------------------------------------------------------- videos: autoplay muted loop, retried on interaction */
const v5pfPending = [];
let v5pfPendingBound = false;
function v5pfEnsurePlays(v) {
  const attempt = () => { const p = v.play(); if (p && p.catch) p.catch(() => { if (v5pfPending.indexOf(v) < 0) v5pfPending.push(v); }); };
  v.addEventListener("canplay", attempt, { once: true });
  v.addEventListener("loadeddata", attempt, { once: true });
  attempt();
  v5pfInView(v, attempt, "0px");
  if (!v5pfPendingBound) {
    v5pfPendingBound = true;
    ["click", "touchstart", "keydown", "scroll"].forEach((evn) => {
      document.addEventListener(evn, () => { v5pfPending.splice(0).forEach((x) => { const p = x.play(); if (p && p.catch) p.catch(() => {}); }); }, { passive: true });
    });
  }
}
function v5pfVideo(el) {
  if (el.__sqs) return; el.__sqs = true;
  const cfg = v5pfJson(el.getAttribute("data-config-video"), {});
  const settings = v5pfJson(el.getAttribute("data-config-settings"), {});
  const player = el.querySelector(".native-video-player") || el;
  let v = player.querySelector("video");
  const autoplay = settings.autoPlay !== false;
  if (!v) {
    const src = el.getAttribute("data-src") || (cfg.systemDataId ? "/assets/sqs-video/zco/" + cfg.systemDataId + ".mp4" : null);
    if (!src) return;
    v = document.createElement("video"); v.src = src; v.preload = "auto"; player.appendChild(v);
  }
  v.setAttribute("playsinline", ""); v.setAttribute("webkit-playsinline", "");
  if (autoplay) { v.autoplay = true; v.muted = true; v.setAttribute("muted", ""); v.setAttribute("autoplay", ""); }
  if (settings.loop !== false) { v.loop = true; v.setAttribute("loop", ""); }
  if (!autoplay || (settings.controls && settings.controls !== "none")) v.controls = true;
  if (cfg.aspectRatio && !player.style.aspectRatio) player.style.aspectRatio = String(cfg.aspectRatio);
  player.classList.add("video-player");
  if (autoplay) v5pfEnsurePlays(v);
}

/* ---------------------------------------------------------------- component */
const V5Portfolio = () => {
  const rootRef = useRef(null);
  const data = window.V5_PORTFOLIO_TILES || { html: "", bodyClasses: [] };

  useEffect(() => {
    const root = rootRef.current;
    if (!root || root.__v5pf) return;
    root.__v5pf = true;
    const cleanups = [];

    // fluid images: now + on load/fonts/resize (the mobile 8-col grid re-flows every block)
    const fluid = Array.from(root.querySelectorAll(".fluid-image-component-root.design-layout-fluid, .image-block-outer-wrapper.design-layout-fluid"));
    const relayout = () => fluid.forEach((r) => { try { v5pfFitFluid(r); } catch (e) {} });
    relayout();
    const relayoutSoon = v5pfDebounce(relayout, 150);
    window.addEventListener("resize", relayoutSoon);
    window.addEventListener("load", relayout);
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(relayout);
    root.querySelectorAll("img").forEach((im) => im.addEventListener("load", relayoutSoon));
    let ro = null;
    if ("ResizeObserver" in window) { ro = new ResizeObserver(relayoutSoon); ro.observe(root); }
    const t1 = setTimeout(relayout, 400), t2 = setTimeout(relayout, 1500);
    cleanups.push(() => { window.removeEventListener("resize", relayoutSoon); window.removeEventListener("load", relayout); if (ro) ro.disconnect(); clearTimeout(t1); clearTimeout(t2); });

    // videos
    Array.from(root.querySelectorAll(".sqs-native-video")).forEach(v5pfVideo);

    // scroll-in state (Squarespace keys image-block styles off .animation-loaded)
    const blocks = Array.from(root.querySelectorAll('.image-block-outer-wrapper[class*="-animation-"]'));
    blocks.forEach((b) => cleanups.push(v5pfInView(b, () => b.classList.add("animation-loaded"))));
    const t3 = setTimeout(() => blocks.forEach((b) => b.classList.add("animation-loaded")), 3000);
    cleanups.push(() => clearTimeout(t3));

    return () => { cleanups.forEach((f) => { try { f(); } catch (e) {} }); root.__v5pf = false; };
  }, []);

  return (
    <section id="portfolio" className="v5-portfolio-section" data-screen-label="Portfolio · Selected work">
      <div
        ref={rootRef}
        className={`v5-portfolio ${data.bodyClasses.join(" ")}`}
        data-archive="zco"
        dangerouslySetInnerHTML={{ __html: data.html }} />
      <div className="v4-container">
        {/* The whole index as colour: one chip per project in its own ground, in /work order.
            The link is the plate itself; the words are secondary. */}
        
      </div>
    </section>
  );
};

Object.assign(window, { V5Portfolio });
