#!/usr/bin/env bash
# End-to-end helper to convert CityGML tiles to tile-local GLBs.
# Assumes heightmaps/textures are already exported so tile_index.csv exists.

set -euo pipefail

ROOT="$(cd "$(dirname "$0")/.." && pwd)"

RAW_DIR="${RAW_DIR:-$ROOT/raw/citygml/lod2}"
CITYJSON_DIR="${CITYJSON_DIR:-$ROOT/work/cityjson}"
CLEAN_DIR="${CLEAN_DIR:-$ROOT/work/cityjson_clean}"
TRI_DIR="${TRI_DIR:-$ROOT/work/cityjson_tri}"
TRI_LOCAL_DIR="${TRI_LOCAL_DIR:-$ROOT/work/cityjson_tri_local}"
SPLIT_DIR="${SPLIT_DIR:-$ROOT/work/cityjson_split_local}"
GLB_DIR="${GLB_DIR:-$ROOT/export_unity/buildings_glb}"
GLB_SPLIT_DIR="${GLB_SPLIT_DIR:-$ROOT/export_unity/buildings_glb_split}"
TILE_INDEX="${TILE_INDEX:-$ROOT/export_unity/tile_index.csv}"

CITYGML_TOOLS="${CITYGML_TOOLS:-$ROOT/tools/citygml-tools-2.4.0/citygml-tools}"
CJIO_CMD="${CJIO:-uv run cjio}"
PYTHON_CMD="${PYTHON_CMD:-uv run python}"

log() {
  printf '[citygml->glb] %s\n' "$*"
}

resolve_cityjson() {
  local path="$1"
  if [[ -f "$path" ]]; then
    echo "$path"
    return 0
  fi
  if [[ -d "$path" ]]; then
    local base
    base="$(basename "$path" .city.json)"
    if [[ -f "$path/$base.json" ]]; then
      echo "$path/$base.json"
      return 0
    fi
    local first
    first="$(find "$path" -maxdepth 1 -name '*.json' | head -n1 || true)"
    if [[ -n "$first" ]]; then
      echo "$first"
      return 0
    fi
  fi
  return 1
}

if [[ ! -f "$TILE_INDEX" ]]; then
  echo "tile_index.csv missing at $TILE_INDEX; run heightmap export first." >&2
  exit 1
fi

mapfile -t GMLS < <(find "$RAW_DIR" -maxdepth 1 -name 'LoD2_*.gml' | sort)
if [[ ${#GMLS[@]} -eq 0 ]]; then
  echo "No CityGML tiles found in $RAW_DIR" >&2
  exit 1
fi

mkdir -p "$CITYJSON_DIR" "$CLEAN_DIR" "$TRI_DIR" "$TRI_LOCAL_DIR" "$SPLIT_DIR" "$GLB_DIR" "$GLB_SPLIT_DIR"

log "CityGML -> CityJSON (${#GMLS[@]} tiles)"
for gml in "${GMLS[@]}"; do
  base="$(basename "$gml" .gml)"
  out="$CITYJSON_DIR/${base}.city.json"
  if [[ -e "$out" ]]; then
    log "skip existing $out"
    continue
  fi
  "$CITYGML_TOOLS" to-cityjson "$gml" -o "$out"
done

log "Clean invalid vertices"
$PYTHON_CMD "$ROOT/scripts/clean_cityjson_vertices.py" --input-dir "$CITYJSON_DIR" --output-dir "$CLEAN_DIR"

log "Triangulate"
mapfile -t CITYJSONS < <(find "$CLEAN_DIR" -maxdepth 1 -name '*.city.json' | sort)
for path in "${CITYJSONS[@]}"; do
  base="$(basename "$path" .city.json)"
  target="$TRI_DIR/${base}.tri.city.json"
  if [[ -e "$target" ]]; then
    log "skip existing $target"
    continue
  fi
  input_json="$(resolve_cityjson "$path" || true)"
  if [[ -z "$input_json" ]]; then
    log "skip $path (cannot resolve json)"
    continue
  fi
  $CJIO_CMD --ignore_duplicate_keys "$input_json" upgrade triangulate vertices_clean save "$target"
done

log "Rebase to tile-local XY"
$PYTHON_CMD "$ROOT/scripts/rebase_cityjson_tiles.py" --input-dir "$TRI_DIR" --output-dir "$TRI_LOCAL_DIR" --tile-index "$TILE_INDEX"

log "Split semantics (roof/wall)"
$PYTHON_CMD "$ROOT/scripts/split_semantics.py" --input-dir "$TRI_LOCAL_DIR" --output-dir "$SPLIT_DIR"

log "Export GLB (base)"
mapfile -t TRIS < <(find "$TRI_LOCAL_DIR" -maxdepth 1 -name '*.tri.city.json' | sort)
for tri in "${TRIS[@]}"; do
  base="$(basename "$tri" .tri.city.json)"
  out="$GLB_DIR/${base}.glb"
  if [[ -e "$out" ]]; then
    log "skip existing $out"
    continue
  fi
  $CJIO_CMD "$tri" export glb "$out"
done

log "Export GLB (roof/wall)"
mapfile -t ROOFS < <(find "$SPLIT_DIR" -maxdepth 1 -name '*.roof.city.json' | sort)
for roof in "${ROOFS[@]}"; do
  base="$(basename "$roof" .roof.city.json)"
  out="$GLB_SPLIT_DIR/${base}_roof.glb"
  if [[ -e "$out" ]]; then
    log "skip existing $out"
    continue
  fi
  $CJIO_CMD "$roof" export glb "$out"
done

mapfile -t WALLS < <(find "$SPLIT_DIR" -maxdepth 1 -name '*.wall.city.json' | sort)
for wall in "${WALLS[@]}"; do
  base="$(basename "$wall" .wall.city.json)"
  out="$GLB_SPLIT_DIR/${base}_wall.glb"
  if [[ -e "$out" ]]; then
    log "skip existing $out"
    continue
  fi
  $CJIO_CMD "$wall" export glb "$out"
done

log "Verify outputs"
$PYTHON_CMD "$ROOT/scripts/verify_pipeline.py" --mode both --tri-dir "$TRI_LOCAL_DIR" --split-dir "$SPLIT_DIR"

log "Done"
