#!/bin/sh
# devrig bootstrap installer (macOS + Linux) - https://devrig.dev/install.sh
#
#   curl -fsSL https://devrig.dev/install.sh | sh
#
# GENERATED by :installer-gen's InstallerGenerator from the resolved JDK model - DO NOT EDIT.
# Every URL + SHA-256 for every supported platform is baked in below; the script
# performs NO live discovery (no GitHub API, no corretto.aws lookups). It downloads
# devrig + a matching JDK 25, verifies SHA-256, unpacks verbatim under
# ~/.mcp-steroid/binaries/<artifact>-<os>-<cpu>-<version>-<sha12>/, and writes a
# launcher into ~/.mcp-steroid/bin/devrig. ALL output to stderr (MCP stdio rule).
# The whole body runs through main(), invoked on the last line, so a truncated
# `curl | sh` transfer can never execute a partial script.

set -eu

VERSION='0.101'
DEVRIG_URL='https://github.com/jonnyzzz/mcp-steroid/releases/download/v0.101/devrig-0.101-40690055.zip'
DEVRIG_SHA256='a7c8cf0d16e23506538bcf7edef6f3164e4b6029cffb37adae2d27f99684e689'
DEVRIG_FORMAT='zip'
# The devrig launcher subpath INSIDE the unpacked dist (computed + asserted by the generator from the
# real zip - `devrig-<version>-<hash>/bin/devrig`). The script runs this launcher and lets devrig itself
# register `~/.mcp-steroid/bin` + PATH (`devrig install devrig`), so the script never writes the wrapper.
DEVRIG_BINSUB='devrig-0.101-40690055/bin/devrig'

STEROID_HOME="$HOME/.mcp-steroid"
BIN_DIR="$STEROID_HOME/bin"
BINARIES_DIR="$STEROID_HOME/binaries"

log()  { printf '%s\n' "[mcp-steroid] $*" >&2; }
fail() { log "ERROR: $*"; exit 1; }

# Atomically promote an unpacked staging tree into its content-addressed target;
# tolerate a concurrent install winning the race (mv nests on collision -> clean up).
promote_tree() {
  if mv "$1" "$2" 2>/dev/null; then
    nested="$2/${1##*/}"
    if [ -d "$nested" ]; then log "another install finished first; using existing tree"; rm -rf "$nested"; fi
  elif [ -d "$2" ]; then
    log "another install finished first; using existing tree"; rm -rf "$1"
  else
    fail "could not move unpacked tree into place: $2"
  fi
}

# install_artifact <kind> <url> <sha256> <format>  -> prints the target dir on stdout
install_artifact() {
  ia_kind="$1"; ia_url="$2"; ia_sha="$3"; ia_fmt="$4"
  ia_sha12=$(printf '%s' "$ia_sha" | cut -c1-12)
  ia_target="$BINARIES_DIR/${ia_kind}-${key}-${VERSION}-${ia_sha12}"
  if [ -d "$ia_target" ]; then
    log "already installed: ${ia_target##*/}"
    printf '%s\n' "$ia_target"; return 0
  fi
  ia_ext=$ia_fmt
  ia_tmp="$BINARIES_DIR/.tmp.$$.${ia_kind}.${ia_ext}"
  ia_unpack="$BINARIES_DIR/.tmp.$$.${ia_kind}.unpack"
  rm -rf "$ia_tmp" "$ia_unpack"
  log "downloading ${ia_kind} ($ia_url)..."
  fetch "$ia_url" "$ia_tmp" || fail "download failed: $ia_url"
  actual=$($sha_tool "$ia_tmp" | awk '{print $1}')
  [ "$actual" = "$ia_sha" ] || fail "SHA-256 mismatch for ${ia_kind}: expected $ia_sha, got $actual"
  log "SHA-256 verified: $ia_sha"
  mkdir -p "$ia_unpack"
  case "$ia_fmt" in
    zip)    unzip -q "$ia_tmp" -d "$ia_unpack" ;;   # unzip presence guaranteed by the preflight below
    tar.gz) tar -xzf "$ia_tmp" -C "$ia_unpack" ;;   # tar presence guaranteed by the preflight below
    tar.xz) tar -xJf "$ia_tmp" -C "$ia_unpack" ;;
    *) fail "unknown archive format '$ia_fmt' for ${ia_kind}" ;;
  esac
  promote_tree "$ia_unpack" "$ia_target"
  rm -f "$ia_tmp"
  printf '%s\n' "$ia_target"
}

main() {
  if [ "$#" -gt 0 ] && [ "${1}" != "install" ]; then
    fail "unknown argument '${1}' (this installer takes no arguments)"
  fi

  # -- platform detection -> normalized <os>-<cpu> key --
  os=${DEVRIG_OS:-}
  cpu=${DEVRIG_CPU:-}
  if [ -z "$os" ]; then
    case "$(uname -s)" in
      Darwin) os=macos ;;
      Linux)  os=linux ;;
      *) fail "unsupported OS '$(uname -s)' - on Windows use install.ps1" ;;
    esac
  fi
  if [ -z "$cpu" ]; then
    case "$(uname -m)" in
      arm64|aarch64) cpu=arm64 ;;
      x86_64|amd64)  cpu=x64 ;;
      *) fail "unsupported CPU architecture '$(uname -m)'" ;;
    esac
  fi
  key="${os}-${cpu}"
  log "platform: ${key}"

  # -- musl/Alpine is NOT supported (the IntelliJ IDEs require glibc) - detect and fail fast --
  if [ "$os" = "linux" ]; then
    if { command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; } \
       || [ -e /lib/ld-musl-x86_64.so.1 ] || [ -e /lib/ld-musl-aarch64.so.1 ]; then
      fail "musl libc (Alpine) is not supported - the IntelliJ IDEs require glibc; use a glibc-based Linux distribution"
    fi
  fi

  # -- BAKED-IN per-platform JDK table (devrig coordinates are universal, set above) --
  jdk_url=''; jdk_sha256=''; jdk_format=''; jdk_javahome=''
  case "$key" in
  macos-arm64)
    jdk_url='https://corretto.aws/downloads/resources/25.0.4.7.1/amazon-corretto-25.0.4.7.1-macosx-aarch64.tar.gz'
    jdk_sha256='41e185be6b230cff4e9c85d33f9b092274a32e42113087f26d3b2e4f7909ab78'
    jdk_format='tar.gz'
    jdk_javahome='amazon-corretto-25.jdk/Contents/Home'
    ;;
  linux-arm64)
    jdk_url='https://corretto.aws/downloads/resources/25.0.4.7.1/amazon-corretto-25.0.4.7.1-linux-aarch64.tar.gz'
    jdk_sha256='90a07c1c693ac9333a8a6ec79432f0d13c0564fec6617b0222d43f86858f65b8'
    jdk_format='tar.gz'
    jdk_javahome='amazon-corretto-25.0.4.7.1-linux-aarch64'
    ;;
  linux-x64)
    jdk_url='https://corretto.aws/downloads/resources/25.0.4.7.1/amazon-corretto-25.0.4.7.1-linux-x64.tar.gz'
    jdk_sha256='1d03a3bd5091728492d92f0ef341aca7d8885ece9a150119558f3e3d62b58745'
    jdk_format='tar.gz'
    jdk_javahome='amazon-corretto-25.0.4.7.1-linux-x64'
    ;;
    macos-x64) fail "Intel macOS (x86_64) is not supported - MCP Steroid ships an Apple-silicon (arm64) JDK only. Use an arm64 Mac." ;;
    *) fail "platform '$key' is not supported by this build" ;;
  esac

  # -- preflight: required tools --
  # This installer NEVER installs system packages. If a prerequisite is missing it lists exactly
  # what to install (and how), then stops - so a missing tool is reported up front, before any
  # download, rather than failing half-way through.
  have_any() { for _c in "$@"; do command -v "$_c" >/dev/null 2>&1 && return 0; done; return 1; }
  missing=''
  add_missing() { missing="${missing}${missing:+|}$1"; }

  have_any curl wget        || add_missing 'curl (or wget) - to download files'
  have_any sha256sum shasum || add_missing 'sha256sum (or shasum) - to verify downloads'
  case " $DEVRIG_FORMAT $jdk_format " in *' zip '*)             have_any unzip || add_missing 'unzip - to extract .zip archives' ;; esac
  case " $DEVRIG_FORMAT $jdk_format " in *' tar.gz '*|*' tar.xz '*) have_any tar || add_missing 'tar - to extract .tar archives' ;; esac

  if [ -n "$missing" ]; then
    log "ERROR: cannot install - required tools are missing, and this installer does not install"
    log "system packages for you. Please install the following, then re-run:"
    pf_ifs=$IFS; IFS='|'
    for m in $missing; do log "  - $m"; done
    IFS=$pf_ifs
    log ""
    log "for example, with your OS package manager:"
    log "    Debian/Ubuntu:  sudo apt-get update && sudo apt-get install -y curl unzip tar"
    log "    Alpine:         sudo apk add curl unzip tar"
    log "    Fedora/RHEL:    sudo dnf install -y curl unzip tar"
    log "    macOS:          curl & tar are preinstalled; run 'brew install unzip' if unzip is missing"
    exit 1
  fi

  # Bind the concrete download + checksum tools now that the preflight proved one of each exists.
  if command -v curl >/dev/null 2>&1; then
    fetch() { curl -fsSL "$1" -o "$2"; }
  else
    fetch() { wget -q "$1" -O "$2"; }
  fi
  if command -v sha256sum >/dev/null 2>&1; then sha_tool="sha256sum"; else sha_tool="shasum -a 256"; fi

  mkdir -p "$BIN_DIR" "$BINARIES_DIR"
  # Sweep orphaned staging from runs killed before cleanup (different $$ each run).
  find "$BINARIES_DIR" -maxdepth 1 -name '.tmp.*' -mtime +0 -exec rm -rf {} + 2>/dev/null \
    || log "WARNING: could not sweep stale .tmp.* entries"

  devrig_target=$(install_artifact devrig "$DEVRIG_URL" "$DEVRIG_SHA256" "$DEVRIG_FORMAT")
  jdk_target=$(install_artifact jdk "$jdk_url" "$jdk_sha256" "$jdk_format")

  # -- locate the unpacked launcher + the bundled JAVA_HOME --
  # DEVRIG_BINSUB is the generator-computed, asserted subpath (devrig-<version>-<hash>/bin/devrig).
  launcher="$devrig_target/$DEVRIG_BINSUB"
  [ -f "$launcher" ] || fail "devrig launcher not found at $launcher"
  chmod +x "$launcher" 2>/dev/null || true

  if [ -n "$jdk_javahome" ]; then jdk_home="$jdk_target/$jdk_javahome"; else jdk_home="$jdk_target"; fi
  [ -x "$jdk_home/bin/java" ] || fail "bin/java not found inside $jdk_home"

  # -- hand off to devrig: it OWNS ~/.mcp-steroid/bin/devrig + PATH (no duplicate wrapper here) --
  # We pass every non-trivial parameter explicitly (the install-tree launcher + the bundled JDK); devrig
  # registers itself. JAVA_HOME is set only so the unpacked devrig runs under the bundled JDK right now.
  # Redirect stdin from /dev/null so devrig inherits an already-closed stdin: when this installer is
  # bootstrapped via `curl | sh`, the parent sh reads stdin from a pipe still open to the shell that
  # ran curl. A devrig subprocess that read stdin (or waited on a prompt) would hang forever with no
  # user recourse. `< /dev/null` gives it an already-closed stdin - `devrig install devrig` is
  # contractually non-interactive (see runInstallDevrigCommand; mirrors the install.ps1 `$null |`).
  log "registering devrig (devrig install devrig)..."
  JAVA_HOME="$jdk_home" "$launcher" install devrig --install-script="$launcher" --jdk-home="$jdk_home" < /dev/null \
    || fail "'devrig install devrig' failed - the launcher could not register itself"

  # -- done. We do NOT auto-register devrig with agents - that edits agent configs, so it is an
  #    explicit user step. --
  log "devrig binary is ready."
  log ""
  log "To register devrig with your agents (Claude, Codex, Gemini), run:"
  log "    devrig install"
}

main "$@"
