#!/bin/sh
# 20260228 ChatGPT
# $Header$
#
# This script creates links from the staging directory to
# the glbs sibling directory.  The staging directory is where the glbs are staged for rendering.  
# The glbs sibling directory is where the PNG & webP batch renderer expects to find the glbs.  The files names
# are sanitized to be filesystem safe and to avoid collisions by adding the path components 
# delimited by double underscores.  

# If a collision is detected, a numeric suffix is added to disambiguate.
# Consequently, the name of the link is not the same as the original glb, but contains the original path 
# components in a sanitized form.  This allows the batch renderer to process all the glbs without worrying 
# about name collisions, while still retaining some traceability to the original files.
#
# For example, if the staging directory contains:
#   /home/jlpoole/work/Voron/test1/Klicky-Probe/Printers/Voron/v1.8_v2.4_Legacy_Trident/v1.8_v2.4_Legacy_Trident_STL/Dock_mount_fixed_v2.glb
# then this script will create the very long file name:
#   glbs/Klicky-Probe__Printers__Voron__...__Dock_mount_fixed_v2.stl.glb
#
# Note: the brackets in a file name, e.g. "[a]" are preserved.
# Another example, if the staging directory contains:
#    /home/jlpoole/work/Voron/test1/Voron/Skirts/[a]_belt_guard_a_x2.stl.glb
# then this script will create the file name:
#   'Voron-2__STLs__Skirts__[a]_belt_guard_a_x2.stl.glb'
#
# Copy/paste:
#   cd ~/work/Voron/renderlab/web/batch_glb_png
#   chmod +x link_glbs.sh
#   ./link_glbs.sh /home/jlpoole/work/Voron/test1
#
# This creates symlinks under ./glbs/ pointing to every *.glb under the staging directory.

set -eu

ROOT="${1:-}"
[ -n "$ROOT" ] || { echo "Usage: $0 /path/to/root" >&2; exit 2; }
[ -d "$ROOT" ] || { echo "ERROR: not a directory: $ROOT" >&2; exit 2; }

OUTDIR="./glbs"
mkdir -p "$OUTDIR"

ts="$(date +%Y%m%d_%H%M%S)"
log="link_glbs_${ts}.log"

# Make ROOT absolute and strip any trailing slash for consistent relpath math.
ROOT_ABS="$(cd "$ROOT" && pwd)"
ROOT_ABS="${ROOT_ABS%/}"

echo "ROOT:    $ROOT_ABS"    | tee "$log"
echo "OUTDIR:  $(cd "$OUTDIR" && pwd)" | tee -a "$log"
echo "LOG:     $log"         | tee -a "$log"
echo ""                     | tee -a "$log"

# Sanitize: turn a path into a filesystem-safe basename.
# Example:
#   Klicky-Probe/Printers/Voron/.../Dock_mount_fixed_v2.stl.glb
# becomes:
#   Klicky-Probe__Printers__Voron__...__Dock_mount_fixed_v2.stl.glb
sanitize() {
  # shellcheck disable=SC2001
  echo "$1" \
  | sed 's|^/||' \
  | sed 's|/|__|g'
  #| sed 's|/|__|g' \
  #| sed 's|[^A-Za-z0-9._-]|_|g'
}

count=0
skipped=0
collisions=0

# Use -print0 to handle spaces safely.
find "$ROOT_ABS" -type f -name '*.glb' -print0 \
| while IFS= read -r -d '' f; do
    # Compute relative path under ROOT_ABS
    rel="${f#$ROOT_ABS/}"

    name="$(sanitize "$rel")"
    linkpath="$OUTDIR/$name"

    # If the link exists and points to the same target, skip quietly.
    if [ -L "$linkpath" ]; then
      target="$(readlink "$linkpath" || true)"
      if [ "$target" = "$f" ]; then
        echo "SKIP (already linked): $linkpath -> $f" >> "$log"
        skipped=$((skipped+1))
        continue
      fi
    fi

    # If the name already exists but points elsewhere, disambiguate.
    if [ -e "$linkpath" ]; then
      i=1
      base="$linkpath"
      while [ -e "$linkpath" ]; do
        linkpath="${base%.glb}_$i.glb"
        i=$((i+1))
      done
      collisions=$((collisions+1))
    fi

    ln -s "$f" "$linkpath"
    echo "LINK: $linkpath -> $f" >> "$log"
    count=$((count+1))
  done

# The while loop runs in a subshell in many /bin/sh implementations,
# so counters above may not update. Summarize by counting log lines instead.
linked_lines="$(grep -c '^LINK: ' "$log" 2>/dev/null || echo 0)"
skipped_lines="$(grep -c '^SKIP ' "$log" 2>/dev/null || echo 0)"

echo "" | tee -a "$log"
echo "DONE. linked=$linked_lines skipped=$skipped_lines (details in $log)" | tee -a "$log"
