#!/usr/bin/env bash
# dot-watch — auto-rerender a graphviz .dot file to PNG on every save.
#
# WHY THIS EXISTS
#   pi-studio renders mermaid natively but has no graphviz/DOT renderer.
#   Its markdown preview DOES render local image links (.png/.jpg/.gif/.webp),
#   and the editor offers "refresh from disk". This helper closes the loop:
#   edit a .dot file -> dot-watch regenerates <name>.png -> hit refresh in
#   Studio to see the update. Uses mtime polling (no inotify dependency,
#   which isn't in the trixie-slim base).
#
# USAGE
#   dot-watch <file.dot> [layout] [dpi]
#     layout: dot|neato|fdp|circo|twopi  (default: dot)
#     dpi:    output resolution           (default: 150)
#   env: DOT_WATCH_INTERVAL=<seconds>     poll interval (default: 1)
#
# EXAMPLES
#   dot-watch /workspace/graph.dot
#   dot-watch graph.dot neato 200

set -euo pipefail

SRC="${1:?usage: dot-watch <file.dot> [layout] [dpi]}"
LAYOUT="${2:-dot}"
DPI="${3:-150}"

[[ -f "$SRC" ]] || { echo "error: no such file: $SRC" >&2; exit 1; }
command -v "$LAYOUT" >/dev/null || { echo "error: layout engine '$LAYOUT' not found" >&2; exit 1; }

OUT="${SRC%.dot}.png"
INTERVAL="${DOT_WATCH_INTERVAL:-1}"   # seconds between polls
ERRLOG="$(mktemp -t dot-watch.XXXXXX.err)"
trap 'rm -f "$ERRLOG"' EXIT

render() {
    if "$LAYOUT" -Tpng -Gdpi="$DPI" "$SRC" -o "$OUT" 2> "$ERRLOG"; then
        printf '[%s] rendered -> %s\n' "$(date +%H:%M:%S)" "$OUT"
    else
        printf '[%s] DOT error:\n' "$(date +%H:%M:%S)"
        sed 's/^/    /' "$ERRLOG"
    fi
}

# portable mtime (GNU stat, fallback to BSD stat)
mtime() { stat -c %Y "$1" 2>/dev/null || stat -f %m "$1" 2>/dev/null; }

echo "watching $SRC ($LAYOUT, ${DPI}dpi) -> $OUT  [Ctrl-C to stop]"
render
last="$(mtime "$SRC")"
while true; do
    sleep "$INTERVAL"
    [[ -f "$SRC" ]] || continue
    now="$(mtime "$SRC")"
    if [[ "$now" != "$last" ]]; then
        last="$now"
        render
    fi
done
