// Credits/colophon data + render — no framework. UMD so the browser gets a
// `HEFCredits` global and `node --test` can require() the pure functions.
//
// The legally load-bearing attribution is per VIDEO clip (CC BY / CC BY-SA need
// the author + license shown to the viewer, and the footage is altered → a
// derivative). That data already ships in clips.json (baked from /api/clips):
// each clip carries free-text `license` + `source`. This module turns that into
// the credits list the public colophon (credits.html) renders. Audio is all
// PD/CC0 and credited as a static courtesy block in the page itself.
(function (root, factory) {
  const api = factory();
  if (typeof module !== "undefined" && module.exports) module.exports = api;
  else root.HEFCredits = api;
})(typeof self !== "undefined" ? self : this, function () {
  "use strict";

  function escapeHtml(s) {
    return String(s == null ? "" : s)
      .replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;");
  }

  // One attribution entry per clip, sorted by id (deterministic). A clip is
  // NEVER silently dropped — even one with an empty license appears, so a
  // missing credit is visible rather than hidden. License/source are the
  // free-text strings authored in the manifest.
  function creditEntries(clips) {
    return (clips || [])
      .map((c) => ({
        id: c.id,
        title: c.title || c.id,
        license: c.license || "",
        source: c.source || "",
      }))
      .sort((a, b) => String(a.id).localeCompare(String(b.id)));
  }

  function creditHtml(e) {
    const lic = e.license
      ? `<span class="lic">${escapeHtml(e.license)}</span>`
      : `<span class="lic missing">license not recorded</span>`;
    const src = e.source ? `<div class="src">${escapeHtml(e.source)}</div>` : "";
    return (
      `<div class="credit">` +
      `<div class="title">${escapeHtml(e.title)}</div>` +
      lic + src +
      `</div>`
    );
  }

  function creditsListHtml(clips) {
    return creditEntries(clips).map(creditHtml).join("");
  }

  // Browser bootstrap: fetch the same clips the experience uses (baked
  // clips.json in the static build, the live API otherwise — the config.js
  // flag, loaded before this script, decides) and fill the container.
  function init(doc, cfg) {
    const fetchUrl = cfg && cfg.static ? "clips.json" : "/api/clips";
    const box = doc.getElementById("video-credits");
    if (!box) return;
    return fetch(fetchUrl)
      .then((r) => r.json())
      .then((d) => { box.innerHTML = creditsListHtml(d.clips || []); })
      .catch((err) => { box.innerHTML = `<p class="err">Could not load credits: ${escapeHtml(err.message)}</p>`; });
  }

  if (typeof document !== "undefined") {
    document.addEventListener("DOMContentLoaded", () => {
      init(document, (typeof window !== "undefined" && window.HEF_CONFIG) || {});
    });
  }

  return { escapeHtml, creditEntries, creditHtml, creditsListHtml, init };
});
