#!/usr/bin/env bash
###############################################################################
# obt-launch-env — Relocatable OBT environment launcher
# Generated by ork deploy (Phase 6)
#
# This script is self-locating: it computes all paths relative to its own
# location, so the deployment can be moved anywhere.
###############################################################################

# Compute DEPLOY_ROOT from this script's location.
# -P / pwd -P resolves symlinks to their physical target so that a symlink
# pointing at .staging (e.g. from a nested utilities folder) doesn't make
# DEPLOY_ROOT differ string-wise from .deploy_path on alternating launches.
# Without this, the relocation fixup ping-pongs ~170 files every time the
# user alternates between launching a symlink-routed app and a direct-path
# app — harmless per-launch but wasteful and confusing.
SCRIPT_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
DEPLOY_ROOT="$SCRIPT_DIR"

# Sever all connections to any host OBT/Python environment.
# Without this, PYTHONPATH from the host leaks in and causes
# the deploy's Python to import obt from the host's site-packages,
# which then discovers source-tree projects instead of deploy projects.
unset PYTHONPATH
unset PYTHONHOME
unset VIRTUAL_ENV
unset OBT_STAGE
unset OBT_ROOT
unset OBT_PROJECT_DIRS
unset OBT_PROJECTS_LIST
unset OBT_SEARCH_PATH
unset OBT_BUILDS
unset OBT_SUBSPACE_DIR
unset OBT_SUBSPACE_LIB_DIR
unset OBT_SUBSPACE_BIN_DIR
unset OBT_SUBSPACE_BUILD_DIR
unset OBT_TARGET
unset ORKID_WORKSPACE_DIR
unset ORKID_ASSET_MANIFEST_DIRS
unset ORKID_IS_MAIN_PROJECT
unset LD_LIBRARY_PATH
unset DYLD_LIBRARY_PATH
unset DYLD_FALLBACK_LIBRARY_PATH
unset PKG_CONFIG
unset PKG_CONFIG_PATH
unset LUA_PATH
# Sever EVERY host OBT_*/ORKID_* var (belt-and-suspenders beyond the explicit
# unsets above). When launched from an existing OBT shell — or a sandbox like
# Flatpak that forwards the caller's environment — stale OBT_MODULES_PATH /
# OBT_BIN_PRIV_DIR / etc. would override the deploy's self-configuration and
# point back at host paths (loading host dep modules, prepending host bins).
for _v in ${!OBT_*} ${!ORKID_*}; do unset "$_v"; done
export PYTHONNOUSERSITE=1

# Bootstrap the OBT framework venv.
# The obt_venv's pyvenv.cfg already tells Python 3.14 where its stdlib is.
export VIRTUAL_ENV="$DEPLOY_ROOT/obt_venv"

# Build PATH: deploy dirs first, then system essentials.
# No homebrew — the deployment is fully self-contained.
export PATH="$DEPLOY_ROOT/obt_venv/bin:$DEPLOY_ROOT/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"

# ---- Bash-level relocation fixup (runs BEFORE Python) ----
# Python cannot start if pyvenv.cfg contains stale paths, so the rewrite
# must happen in bash before we exec the interpreter.
#
# Bundle time writes every text file containing a build path with the
# sentinel __OBT_DEPLOY_SENTINEL__ in place of the real path, and emits
# .relocatable_files listing every such file. Launch time reads that
# manifest and substitutes sentinel -> DEPLOY_ROOT in each entry — no
# filesystem walk, O(N) where N = relocatable file count.
_MARKER_FILE="$DEPLOY_ROOT/.deploy_path"
_MANIFEST="$DEPLOY_ROOT/.relocatable_files"
_NEED_FIXUP=0
if [ -f "$_MARKER_FILE" ]; then
  _OLD_ROOT="$(cat "$_MARKER_FILE")"
  if [ "$_OLD_ROOT" != "$DEPLOY_ROOT" ]; then
    _NEED_FIXUP=1
  fi
else
  echo "$DEPLOY_ROOT" > "$_MARKER_FILE"
fi

if [ "$_NEED_FIXUP" -eq 1 ]; then
  echo "[deploy-fixup] Relocation detected: $_OLD_ROOT -> $DEPLOY_ROOT"
  if [ ! -f "$_MANIFEST" ]; then
    echo "[deploy-fixup] FATAL: manifest $_MANIFEST missing — cannot relocate" >&2
    exit 1
  fi
  _n=0
  while IFS= read -r _rel; do
    [ -z "$_rel" ] && continue
    _f="$DEPLOY_ROOT/$_rel"
    [ -f "$_f" ] || continue
    [ -L "$_f" ] && continue
    sed -i '' "s|$_OLD_ROOT|$DEPLOY_ROOT|g" "$_f" && _n=$((_n+1))
  done < "$_MANIFEST"
  echo "$DEPLOY_ROOT" > "$_MARKER_FILE"
  echo "[deploy-fixup] Done ($_n files updated)."
fi

# ---- Effective stage dir + writable caches ----
# OBT (Python) and the engine (C++, via $OBT_STAGE) resolve the mutable dirs as
# <stage>/{assetcache,envmaps,dblockcache,tempdir}. Those MUST be writable; the
# convention is to symlink them to the user's global ~/.obt-global/<name>.
#
#   * writable DEPLOY_ROOT  -> symlink the caches into it directly (classic).
#   * read-only DEPLOY_ROOT (a deployed bundle, e.g. a Flatpak /app) -> build a
#     writable "stage mirror" in $HOME: symlink every read-only tree entry, and
#     point the mutable dirs at ~/.obt-global. OBT_STAGE is then the mirror, so
#     every <stage>/assetcache lookup (Python and C++) lands in the writable
#     ~/.obt-global/assetcache. $ORIGIN rpaths still resolve (symlinks resolve to
#     the real /app/orkid/lib) and the sentinel-baked text paths stay readable.
_OG="$HOME/.obt-global"
mkdir -p "$_OG/assetcache" "$_OG/envmaps" "$_OG/dblockcache" "$_OG/tempdir"
_MUTABLE="assetcache envmaps dblockcache tempdir"
STAGE_DIR="$DEPLOY_ROOT"
if [ -w "$DEPLOY_ROOT" ]; then
  for _w in assetcache envmaps; do
    [ -e "$DEPLOY_ROOT/$_w" ] || ln -s "$_OG/$_w" "$DEPLOY_ROOT/$_w" 2>/dev/null || true
  done
else
  STAGE_DIR="$_OG/stage"
  mkdir -p "$STAGE_DIR"
  for _e in "$DEPLOY_ROOT"/* "$DEPLOY_ROOT"/.[!.]*; do
    [ -e "$_e" ] || continue
    _b="$(basename "$_e")"
    case " $_MUTABLE " in *" $_b "*) continue ;; esac
    ln -sfn "$_e" "$STAGE_DIR/$_b"
  done
  for _w in $_MUTABLE; do
    ln -sfn "$_OG/$_w" "$STAGE_DIR/$_w"
  done
fi

# Source user/machine-specific configuration (audio devices, CDN keys, etc.)
if [ -f "$DEPLOY_ROOT/obt_config/env.common.sh" ]; then
  source "$DEPLOY_ROOT/obt_config/env.common.sh"
fi

# Discover projects: any directory under projects/ that contains obt.project/
OBT_PROJECT_ARGS=()
for proj_dir in "$DEPLOY_ROOT/projects"/*/; do
  if [ -d "${proj_dir}obt.project" ]; then
    # Strip trailing slash for clean path
    OBT_PROJECT_ARGS+=(--project "${proj_dir%/}")
  fi
done

# Detect CPU core count
NUM_CORES=$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4)

# Launch OBT environment — invoke python explicitly to bypass hardcoded shebangs
exec "$DEPLOY_ROOT/obt_venv/bin/python3" \
  "$DEPLOY_ROOT/obt_venv/bin/obt.env.launch.py" \
  --stagedir "$STAGE_DIR" \
  --numcores "$NUM_CORES" \
  "${OBT_PROJECT_ARGS[@]}" \
  "$@"
