#!/bin/bash
# model-docs --- generate the BSPPFit model API documentation with
# openscad-docsgen, rendering the example images, and KEEP the result for
# visual review. This is the companion of model-doc-check: that one only
# validates and then discards its output, this one produces and keeps the
# browsable Markdown wiki.
#
# Output goes to the DocsDirectory named in .openscad_docsgen_rc
# (api.wiki/ by default): per-file Markdown, the rendered PNG examples,
# and the wiki index pages (TOC, AlphaIndex, Topics, CheatSheet, Sidebar),
# matching the rc's GenerateDocs list.
#
# Prerequisites (same as model-doc-check):
#   - openscad-docsgen on PATH (pip/pipx puts it under ~/.local/bin, added
#     to PATH below), actually RUNNABLE, not merely present: a self-test
#     below catches the case where the console-script wrapper's own
#     baked-in interpreter can no longer find the openscad_docsgen module
#     (typically after a Python version change), which `command -v` alone
#     would miss.
#   - openscad on PATH, runnable NON-INTERACTIVELY (a wrapper around an
#     AppImage or .app bundle must forward its arguments: end it with
#     exec .../OpenSCAD "$@", or use a symlink). Image rendering really
#     exercises this, unlike the test-only gate in model-doc-check.
#   - BOSL2 reachable as a directory named exactly "BOSL2" on OPENSCADPATH
#   - on a headless box, Xvfb (the script wraps itself in xvfb-run when no
#     DISPLAY is set)
#
# Usage: model-docs [extra openscad-docsgen args]
set -euo pipefail

# pip/pipx install the openscad-docsgen console script under ~/.local/bin.
case ":$PATH:" in
    *":$HOME/.local/bin:"*) : ;;
    *) PATH="$HOME/.local/bin:$PATH" ;;
esac
export PATH

ROOT=$(cd "$(dirname "$0")" && pwd)
SRC="bsppfit.scad"          # relative: docsgen mis-places output for an
                            # absolute path (see model-doc-check).

# --- library path: examples resolve <BOSL2/...> and <bsppfit.scad>.
if [ -z "${OPENSCADPATH:-}" ]; then
    for d in "$HOME/libraries" \
             "$HOME/.local/share/OpenSCAD/libraries" \
             "$HOME/Documents/OpenSCAD/libraries" \
             "$HOME/Library/Application Support/OpenSCAD/libraries"; do
        if [ -d "$d/BOSL2" ]; then OPENSCADPATH="$d"; break; fi
    done
fi
OPENSCADPATH="${OPENSCADPATH:-}:$ROOT"
export OPENSCADPATH

# --- tool checks
# Existence on PATH is necessary but not sufficient: a console-script
# wrapper (as pip/pipx install for openscad-docsgen) has its own
# interpreter baked into its shebang line at install time, and that
# specific interpreter can lose access to the module it wraps --- most
# commonly after a Python version change alters which interpreter an
# unversioned "python3" shebang resolves to, orphaning a package
# installed under the previous version's --user site-packages.
# `command -v` alone does not catch this: the wrapper file still exists
# and is executable, it just fails the moment it actually runs. This is
# exactly the failure a project author hit (2026-09-05): openscad-docsgen
# was found on PATH, so the check below passed, but the real
# documentation-generation run below THAT failed with a raw Python
# traceback ("ModuleNotFoundError: No module named 'openscad_docsgen'"),
# which this project's own Makefile then reported as the unhelpfully
# generic "model-docs unavailable". Reproduced directly (a wrapper
# script pointed at a Python interpreter that genuinely lacks the
# module) before writing this self-test, not assumed from the symptom
# report alone.
for t in openscad-docsgen openscad; do
    command -v "$t" >/dev/null 2>&1 || {
        echo "model-docs: error: '$t' not found on PATH" >&2; exit 2; }
done
if ! DOCSGEN_SELFTEST=$(openscad-docsgen --help 2>&1); then
    DOCSGEN_PATH=$(command -v openscad-docsgen)
    echo "model-docs: error: 'openscad-docsgen' is on PATH but failed to run." >&2
    echo "model-docs: its own error output:" >&2
    echo "$DOCSGEN_SELFTEST" | sed 's/^/model-docs:   /' >&2
    echo "model-docs: this usually means the console-script wrapper's" >&2
    echo "model-docs: own interpreter (baked into its shebang line at" >&2
    echo "model-docs: install time) can no longer find the openscad_docsgen" >&2
    echo "model-docs: module --- typically after a Python version change." >&2
    echo "model-docs: found at: $DOCSGEN_PATH" >&2
    echo "model-docs: its shebang (the interpreter or venv it targets):" >&2
    echo "model-docs:   $(head -1 "$DOCSGEN_PATH" 2>/dev/null || echo '(could not read it)')" >&2
    echo "model-docs: (a pipx-managed install's shebang contains pipx/venvs/;" >&2
    echo "model-docs: a plain pip install shows a system or --user python3." >&2
    echo "model-docs: Printed directly above, not left for you to re-check in a" >&2
    echo "model-docs: separate shell: this script prepends ~/.local/bin to its" >&2
    echo "model-docs: own PATH if not already present (pip/pipx's usual install" >&2
    echo "model-docs: location), so a plain 'command -v openscad-docsgen' run in" >&2
    echo "model-docs: your own shell can genuinely fail even though this script" >&2
    echo "model-docs: finds it fine --- that is not a contradiction, it is this" >&2
    echo "model-docs: PATH prepending working as intended; see PATH in the man" >&2
    echo "model-docs: page's ENVIRONMENT section.)" >&2
    echo "model-docs: To fix, reinstall with whichever tool manages it:" >&2
    echo "model-docs:   pipx install --force openscad-docsgen" >&2
    echo "model-docs:   python3 -m pip install --user --force-reinstall openscad-docsgen" >&2
    exit 2
fi

# --- headless: wrap in a virtual X server if there is no display
RUN=""
if [ -z "${DISPLAY:-}" ] && command -v xvfb-run >/dev/null 2>&1; then
    RUN="xvfb-run -a"
fi

DOCSDIR=$(awk -F': *' '/^DocsDirectory:/{print $2; exit}' \
          "$ROOT/.openscad_docsgen_rc" 2>/dev/null)
DOCSDIR=${DOCSDIR:-docs}
DOCSDIR=${DOCSDIR%/}        # normalise: drop any trailing slash
cd "$ROOT"

# Full generation: per-file docs (-m) + wiki index pages
# (-i AlphaIndex, -I Topics, -t TOC, -c CheatSheet, -s Sidebar), forcing
# image regeneration (-f). No -n and no -T, so the example PNGs render.
echo "model-docs: generating into $DOCSDIR/ (rendering example images; this is the slow path)"
$RUN openscad-docsgen -m -i -I -t -c -s -f "$SRC" "$@"

echo "model-docs: done. Browse $DOCSDIR/ (start at $DOCSDIR/TOC.md)."
