<?php

declare(strict_types=1);

/**
 * The gallery browser (1.5.5): every piece on the shelf, rendered, ten
 * to a page. The dropdowns stay the fast path on a small board; this is
 * the walk-the-aisles view for the big one. Pieces are decoded
 * server-side and embedded, then painted client-side by the exact
 * renderer callers see (cp437render + the board's ANSI parser).
 */

require __DIR__ . '/_lib.php';
admin_require();

$perPage = 10;
$pieces = \Atdt\Art::pieces();
$pages = max(1, (int)ceil(count($pieces) / $perPage));
$page = max(1, min($pages, (int)($_GET['page'] ?? 1)));
$slice = array_slice($pieces, ($page - 1) * $perPage, $perPage);

$cards = [];
foreach ($slice as $slot) {
    $bytes = \Atdt\Art::bytes($slot);
    if ($bytes === null) {
        continue;
    }
    [, $sauce] = \Atdt\Cp437::splitSauce($bytes);
    $cards[] = [
        'slot' => $slot,
        'text' => \Atdt\Cp437::loadAns($bytes),
        'ice' => (bool)(((int)($sauce['flags'] ?? 0)) & 1),
        'rows' => (int)($sauce['tinfo2'] ?? 0),
        'title' => (string)($sauce['title'] ?? ''),
        'author' => (string)($sauce['author'] ?? ''),
        'bytes' => strlen($bytes),
    ];
}

$glyphs = [];
for ($b = 0; $b < 256; $b++) {
    $glyphs[] = mb_ord(\Atdt\Cp437::toGlyph($b), 'UTF-8');
}

admin_page_start('Gallery', 'gallery');
?>

<p class="hint"><?= count($pieces) ?> piece<?= count($pieces) === 1 ? '' : 's' ?> on the shelf
(<code>data/art/</code>). Everything here can be worn by a theme screen, a menu backdrop or
variant, a bulletin, or the <code>ART</code> action -- and opened in the
<a href="editor.php">ANSI editor</a>. The board shows rows 1-25.</p>

<?php if ($pieces === []): ?>
<div class="card"><p class="hint">The shelf is bare. Draw something in the
<a href="editor.php">ANSI editor</a> or import a classic .ans there.</p></div>
<?php endif; ?>

<div class="gallerygrid">
<?php foreach ($cards as $i => $c): ?>
  <div class="card galcard">
    <div class="galhead">
      <strong><code><?= h($c['slot']) ?></code></strong>
      <span class="hint"><?= (int)$c['rows'] > 0 ? (int)$c['rows'] . ' rows · ' : '' ?><?= number_format($c['bytes'] / 1024, 1) ?> KB</span>
    </div>
    <canvas class="galcanvas" id="gal<?= $i ?>" width="640" height="400"></canvas>
    <div class="galfoot">
      <span class="hint"><?= h(trim($c['title'] . ($c['author'] !== '' ? ' - ' . $c['author'] : ''))) ?></span>
      <a class="btn small" href="editor.php?open=<?= h($c['slot']) ?>">Open in editor</a>
    </div>
  </div>
<?php endforeach; ?>
</div>

<?php if ($pages > 1): ?>
<p class="galpager">
  <?php if ($page > 1): ?><a class="btn small secondary" href="gallery.php?page=<?= $page - 1 ?>">&laquo; Newer</a><?php endif; ?>
  page <?= $page ?> of <?= $pages ?>
  <?php if ($page < $pages): ?><a class="btn small secondary" href="gallery.php?page=<?= $page + 1 ?>">Older &raquo;</a><?php endif; ?>
</p>
<?php endif; ?>

<style>
.gallerygrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 14px; }
.galcard { padding: 10px; }
.galhead, .galfoot { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 4px 0; }
.galcanvas { width: 100%; height: auto; display: block; background: #000; border: 1px solid #222; }
.galpager { display: flex; align-items: center; gap: 12px; margin-top: 14px; }
</style>

<script id="gal-config" type="application/json"><?= json_encode([
    'glyphs' => $glyphs,
    'font' => '../' . atdt_asset('assets/fonts/Web437_IBM_VGA_8x16.woff'),
    'cards' => array_map(
        fn(array $c) => ['text' => $c['text'], 'ice' => $c['ice'], 'rows' => $c['rows']],
        $cards
    ),
], JSON_HEX_TAG) ?></script>
<script src="../<?= h(atdt_asset('assets/cp437render.js')) ?>"></script>
<script src="../<?= h(atdt_asset('assets/term.js')) ?>"></script>
<script src="../<?= h(atdt_asset('assets/editor.js')) ?>"></script>
<script>
(function () {
    "use strict";
    var cfg = JSON.parse(document.getElementById("gal-config").textContent);
    var painters = [];
    cfg.cards.forEach(function (card, i) {
        // The editor core parses exactly like the board, then trims.
        var core = new AtdtEd.EditorCore(cfg.glyphs, 25);
        core.importText(card.text, card.ice);
        var cv = document.getElementById("gal" + i);
        var p = new Cp437Render.CanvasPainter(cv, core.buf);
        painters.push(p);
        p.repaint();
    });
    Cp437Render.loadFont(cfg.font, function (fam) {
        painters.forEach(function (p) { p.setFont(fam); });
    });
})();
</script>

<?php admin_page_end(); ?>
