#!/bin/bash
# api2doc --- render the model API documentation (the Markdown produced by
# model-docs / openscad-docsgen) into a single consolidated, self-contained
# HTML page and a PDF, wired into the BSPPFit documentation set: the same
# stylesheet, the Index back-link, the authoring/version block, and the
# HTML-to-PDF link as the Org-exported documents carry.
#
# It is the docsgen-Markdown analogue of man2htmldoc, which does the
# same job for the groff man pages.
#
# Usage: api2doc [--html|--pdf|--all] [version]
#   --html|--pdf|--all   which rendition(s) to build (default: --all). The
#                        html and pdf make targets pass --html / --pdf so
#                        each builds only its own format.
#   version   package version for the title block (default: read from the
#             VERSION file, else 0.0.0).
#
# Inputs come from the rc DocsDirectory (api.wiki/, populated by
# "make model-docs"); outputs are bsppfit-api.html and
# bsppfit-api.pdf.
#
# Requires pandoc. The PDF step also needs lualatex (the engine the
# project's Org PDF chain uses); without it the HTML is still written and
# the PDF is skipped with a warning.
set -euo pipefail

# Optional first argument selects which rendition(s) to build, so the html
# and pdf make targets can each produce just their own format; default both.
MODE=all
case "${1:-}" in
    --html) MODE=html; shift ;;
    --pdf)  MODE=pdf;  shift ;;
    --all)  MODE=all;  shift ;;
esac

ROOT=$(cd "$(dirname "$0")" && pwd)
VERSION="${1:-$(tail -n1 "$ROOT/VERSION" 2>/dev/null || echo 0.0.0)}"

command -v pandoc >/dev/null 2>&1 || {
    echo "api2doc: error: pandoc not found on PATH" >&2; exit 2; }

# The consolidated source is the per-file page docsgen writes for the
# library; every documented symbol lives in it, so its See-Also anchors all
# resolve within the one page.
DOCSDIR=$(awk -F': *' '/^DocsDirectory:/{print $2; exit}' \
          "$ROOT/.openscad_docsgen_rc" 2>/dev/null)
DOCSDIR=${DOCSDIR:-api.wiki}; DOCSDIR=${DOCSDIR%/}
SRC_MD="$ROOT/$DOCSDIR/bsppfit.scad.md"
[ -f "$SRC_MD" ] || {
    echo "api2doc: error: $SRC_MD not found; run 'make model-docs' first" >&2
    exit 3; }
IMG_DIR=$(dirname "$SRC_MD")        # example images are relative to the .md

OUT_HTML="$ROOT/bsppfit-api.html"
OUT_PDF="$ROOT/bsppfit-api.pdf"

# Authoring credit, kept in step with the rest of the docs by reading the
# ASSISTANT macro straight from version.org.in.
ASSISTANT=$(sed -n 's/^#+MACRO: ASSISTANT //p' \
            "$ROOT/version.org.in" 2>/dev/null)
ASSISTANT=${ASSISTANT:-the LLM assistant}

# Index back-link target, kept in step with the rest of the docs (and any
# ./configure INDEX=... override) by reading the substituted INDEX_HTML
# variable straight from the generated Makefile --- the one file every
# AC_SUBST'd configure.ac variable is guaranteed to land in, whether or not
# Makefile.am itself references it. Falls back to the project default if
# Makefile hasn't been generated yet (api2doc run before ./configure).
INDEX_HTML=$(sed -n 's/^INDEX_HTML *= *//p' "$ROOT/Makefile" 2>/dev/null | head -n1 || true)
INDEX_HTML=${INDEX_HTML:-Index.html}

WORK=$(mktemp -d "${TMPDIR:-/tmp}/bsppfit-api2doc.XXXXXX")
trap 'rm -rf "$WORK"' EXIT

# Preprocess the docsgen Markdown for a single consolidated document:
#   - drop the wiki's cross-page Topics links (there is no Topics page in a
#     standalone document), keeping each link's visible label;
#   - turn the raw <img> example tags into Markdown images, so they render
#     in BOTH backends (pandoc discards raw HTML in its LaTeX/PDF output).
PRE="$WORK/api.md"
python3 - "$SRC_MD" "$PRE" <<'PY'
import re, sys
s = open(sys.argv[1]).read()
s = re.sub(r'\[([^\]]*)\]\(Topics[^)]*\)', r'\1', s)
def img(m):
    t   = m.group(0)
    alt = (re.search(r'alt="([^"]*)"', t) or [None, ""])[1]
    src = (re.search(r'src="([^"]*)"', t) or [None, ""])[1]
    return f'![{alt}]({src})'
s = re.sub(r'<img\b[^>]*>', img, s)
open(sys.argv[2], "w").write(s)
PY

# Title/version metadata. The author block sits in the title block for the
# PDF (as the Org-exported PDFs carry it via \maketitle) but at the foot of
# the HTML page (as the Org HTML postamble places it); so the HTML metadata
# omits the author and a footer supplies it after the body.
cat > "$WORK/meta-pdf.yaml" <<EOF
---
title: "BSPPFit Model API Reference"
subtitle: "v$VERSION"
author:
  - "Peter Felecan"
  - "assisted by $ASSISTANT"
---
EOF
cat > "$WORK/meta-html.yaml" <<EOF
---
title: "BSPPFit Model API Reference"
subtitle: "v$VERSION"
---
EOF

# Author block placed at the end of the HTML page, matching the "Author:"
# postamble the Org documents emit.
cat > "$WORK/footer.html" <<EOF
<hr style="margin-top:2.5em;">
<footer style="font-family:sans-serif; font-size:0.9em;">
<p class="author">Author: Peter Felecan <br> <small><em>assisted by $ASSISTANT</em></small></p>
</footer>
EOF

# Header strip: Index back-link (left) and PDF link (right), in the shape of
# batch-init.el's bsppfit/html-preamble, plus the stylesheet shared with
# Index.org and man2htmldoc.
cat > "$WORK/nav.html" <<EOF
<nav class="bsppfit-back" style="font-family:sans-serif; font-size:0.9em; border-bottom:1px solid #ddd; padding-bottom:0.4em; margin-bottom:1em; display:flex; justify-content:space-between;">
<span class="bsppfit-back-left"><a href="$INDEX_HTML">&#x2190; Index</a></span>
<span class="bsppfit-back-right"><a href="bsppfit-api.pdf">PDF &#x2193;</a></span>
</nav>
EOF
cat > "$WORK/style.html" <<'EOF'
<style>
  body { font-family: sans-serif; max-width: 760px; margin: 2em auto; }
  h1   { border-bottom: 2px solid #444; padding-bottom: 0.3em; }
  h2   { margin-top: 1.5em; color: #222; }
  a    { color: #0055aa; }
  pre, code { font-family: monospace; }
  img  { max-width: 100%; height: auto; }
</style>
EOF

if [ "$MODE" = html ] || [ "$MODE" = all ]; then
    echo "api2doc: HTML -> ${OUT_HTML#$ROOT/}"
    pandoc --from gfm --to html5 --standalone --embed-resources \
        --resource-path="$IMG_DIR" \
        --metadata-file="$WORK/meta-html.yaml" \
        --include-in-header="$WORK/style.html" \
        --include-before-body="$WORK/nav.html" \
        --include-after-body="$WORK/footer.html" \
        "$PRE" -o "$OUT_HTML"
fi

if [ "$MODE" = pdf ] || [ "$MODE" = all ]; then
    if command -v lualatex >/dev/null 2>&1; then
        echo "api2doc: PDF  -> ${OUT_PDF#$ROOT/}"
        pandoc --from gfm --to pdf --pdf-engine=lualatex \
            -V geometry:margin=2.5cm -V colorlinks=true \
            --resource-path="$IMG_DIR" \
            --metadata-file="$WORK/meta-pdf.yaml" \
            "$PRE" -o "$OUT_PDF"
    else
        echo "api2doc: lualatex not found; PDF skipped." >&2
    fi
fi
echo "api2doc: done."
