<h1>Library</h1>
<div class="pagebar"><span id="libcount"></span></div>
<div class="filterbar" role="group" aria-label="filter by kind">
  <input type="search" id="libsearch" placeholder="search your games…" aria-label="search library">
  <button type="button" data-kind="" aria-pressed="true">All</button>
  <button type="button" data-kind="boardgame" aria-pressed="false">Board games</button>
  <button type="button" data-kind="rpgitem" aria-pressed="false">RPGs</button>
</div>
<div id="libbody"></div>
<script>
"use strict";
let GAMES = [];
let KIND = "";  // "" = all; "boardgame" also covers expansions

function gameCard(g) {
  const art = g.thumbnail || g.image;
  const players = g.min_players
    ? (g.min_players === g.max_players ? `${g.min_players}` : `${g.min_players}–${g.max_players}`) + " players"
    : "";
  const time = g.playtime ? `${g.playtime} min` : "";
  const weight = g.weight ? `weight ${g.weight.toFixed(1)}` : "";
  const rank = g.rank ? `BGG rank ${g.rank}` : "";
  return `
  <article class="game">
    ${art
      ? `<img src="${esc(art)}" alt="" loading="lazy">`
      : `<div class="noart" aria-hidden="true">${esc((g.name || "?").charAt(0).toUpperCase())}</div>`}
    <div class="info">
      <div class="gname">${esc(g.name)}${g.year ? ` <span class="meta">(${esc(g.year)})</span>` : ""}
        ${g.type === "rpgitem" ? `<span class="chip open">RPG · local only</span>` : ""}</div>
      <div class="gmeta">${[players, time, weight, rank].filter(Boolean).map(esc).join(" · ")}</div>
      ${g.version ? `<div class="gmeta">${esc(g.version.name || "")}</div>` : ""}
    </div>
  </article>`;
}

function matchesKind(g) {
  if (!KIND) return true;
  if (KIND === "boardgame") return g.type !== "rpgitem";
  return g.type === "rpgitem";
}

function render() {
  const q = document.getElementById("libsearch").value.trim().toLowerCase();
  let rows = GAMES.filter(matchesKind);
  if (q) rows = rows.filter(g =>
    (g.name + " " + (g.designers || []).join(" ")).toLowerCase().includes(q));
  document.getElementById("libcount").innerHTML =
    `<b>${rows.length}</b> of <b>${GAMES.length}</b> game(s)`;
  document.getElementById("libbody").innerHTML = rows.length
    ? `<div class="shelfgrid">${rows.map(gameCard).join("")}</div>`
    : `<p class="empty">${GAMES.length
        ? "No games match that search."
        : `Your library appears here after <b>enrich</b> runs — full metadata for
           every cataloged game: art, player counts, playtime, and more.<br>
           Run the pipeline through <code>enrich</code> to fill these shelves.`}</p>`;
}

let LAST = null;
async function refresh() {
  const games = await fetchJSON("/api/library");
  const payload = JSON.stringify(games);
  if (payload === LAST) return;
  LAST = payload;
  GAMES = games;
  render();
}

document.getElementById("libsearch").addEventListener("input", render);
document.querySelectorAll("[data-kind]").forEach(b => b.addEventListener("click", () => {
  KIND = b.dataset.kind;
  document.querySelectorAll("[data-kind]").forEach(o =>
    o.setAttribute("aria-pressed", String(o === b)));
  render();
}));
refresh().catch(err => errorBanner(err.message || err));
pollLoop(refresh, 10000, () => showBanner(""));
</script>
