#!/bin/sh
# RunMat CLI installer.
#   curl -fsSL https://runmat.com/install.sh | sh
#   curl -fsSL https://runmat.com/install.sh | sh -s -- --with-desktop-and-agent

set -eu

MANIFEST_URL="${RUNMAT_INSTALL_MANIFEST_URL:-https://updates.runmat.com/prod/install-manifest.tsv}"
BIN_DIR="${RUNMAT_BIN_DIR:-$HOME/.local/bin}"
APP_DIR="${RUNMAT_APP_DIR:-$HOME/Applications}"
INCLUDE_DESKTOP_AND_AGENT=0

while [ "$#" -gt 0 ]; do
  case "$1" in
    --with-desktop-and-agent) INCLUDE_DESKTOP_AND_AGENT=1 ;;
    --cli-only|--yes|-y|--noninteractive) ;;
    --bin-dir) shift; BIN_DIR="${1:?--bin-dir requires a path}" ;;
    --app-dir) shift; APP_DIR="${1:?--app-dir requires a path}" ;;
    *) printf 'Unknown option: %s\n' "$1" >&2; exit 2 ;;
  esac
  shift
done

command -v curl >/dev/null 2>&1 || { echo "curl is required" >&2; exit 1; }
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
ARCH="$(uname -m)"
case "$OS/$ARCH" in
  darwin/arm64) PLATFORM="darwin-aarch64" ;;
  darwin/x86_64) PLATFORM="darwin-x86_64" ;;
  linux/x86_64) PLATFORM="linux-x86_64" ;;
  *) echo "RunMat does not publish an installer for $OS/$ARCH yet." >&2; exit 1 ;;
esac
if [ "$OS" = "linux" ] && [ -z "${RUNMAT_APP_DIR:-}" ]; then APP_DIR="$HOME/.local/bin"; fi

TEMP_DIR="$(mktemp -d)"
MOUNT_DIR=""
cleanup() {
  if [ -n "$MOUNT_DIR" ] && mount | grep -Fq "on $MOUNT_DIR "; then hdiutil detach "$MOUNT_DIR" -quiet || true; fi
  rm -rf "$TEMP_DIR"
}
trap cleanup EXIT INT TERM

echo "Fetching the RunMat distribution manifest..."
curl -fsSL "$MANIFEST_URL" -o "$TEMP_DIR/install-manifest.tsv"
MANIFEST_ROW="$(awk -F '\t' -v platform="$PLATFORM" '$1 == "1" && $2 == platform { print; exit }' "$TEMP_DIR/install-manifest.tsv")"
[ -n "$MANIFEST_ROW" ] || { echo "Distribution has no payload for $PLATFORM" >&2; exit 1; }
OLD_IFS=$IFS
IFS="$(printf '\t')"
read -r SCHEMA PLATFORM_FIELD VERSION TOOLS_URL TOOLS_SHA256 DESKTOP_URL DESKTOP_KIND DESKTOP_SHA256 <<EOF
$MANIFEST_ROW
EOF
IFS=$OLD_IFS
[ "$SCHEMA" = "1" ] && [ "$PLATFORM_FIELD" = "$PLATFORM" ] || { echo "Unsupported RunMat install manifest" >&2; exit 1; }

sha256_file() {
  if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | awk '{print $1}'
  elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | awk '{print $1}'
  elif command -v openssl >/dev/null 2>&1; then openssl dgst -sha256 -r "$1" | awk '{print $1}'
  else echo "A SHA-256 utility (sha256sum, shasum, or openssl) is required." >&2; return 1
  fi
}

TOOLS_ARCHIVE="$TEMP_DIR/tools.archive"
curl -fL "$TOOLS_URL" -o "$TOOLS_ARCHIVE"
ACTUAL_SHA="$(sha256_file "$TOOLS_ARCHIVE")"
[ "$ACTUAL_SHA" = "$TOOLS_SHA256" ] || { echo "Command-line tools archive failed SHA-256 verification." >&2; exit 1; }
mkdir -p "$TEMP_DIR/tools" "$BIN_DIR"
case "$TOOLS_URL" in
  *.zip) command -v unzip >/dev/null 2>&1 || { echo "unzip is required" >&2; exit 1; }; unzip -q "$TOOLS_ARCHIVE" -d "$TEMP_DIR/tools" ;;
  *) tar -xzf "$TOOLS_ARCHIVE" -C "$TEMP_DIR/tools" ;;
esac
for file in "$TEMP_DIR/tools"/*; do
  case "$(basename "$file")" in
    manifest.json|cli-tools-state.json) continue ;;
    runmat-agent)
      [ "$INCLUDE_DESKTOP_AND_AGENT" -eq 1 ] || continue
      ;;
  esac
  cp "$file" "$BIN_DIR/"
done
chmod +x "$BIN_DIR/runmat"
if [ "$INCLUDE_DESKTOP_AND_AGENT" -eq 1 ]; then chmod +x "$BIN_DIR/runmat-agent"; fi

case ":$PATH:" in *":$BIN_DIR:"*) ;; *) echo "Add $BIN_DIR to PATH to use RunMat from a new terminal." ;; esac

if [ "$INCLUDE_DESKTOP_AND_AGENT" -eq 1 ]; then
  DESKTOP_PACKAGE="$TEMP_DIR/desktop-package"
  curl -fL "$DESKTOP_URL" -o "$DESKTOP_PACKAGE"
  ACTUAL_DESKTOP_SHA="$(sha256_file "$DESKTOP_PACKAGE")"
  [ "$ACTUAL_DESKTOP_SHA" = "$DESKTOP_SHA256" ] || { echo "Desktop installer failed SHA-256 verification." >&2; exit 1; }
  case "$OS/$DESKTOP_KIND" in
    darwin/dmg)
      MOUNT_DIR="$TEMP_DIR/mount"
      mkdir -p "$MOUNT_DIR" "$APP_DIR"
      hdiutil attach "$DESKTOP_PACKAGE" -nobrowse -quiet -mountpoint "$MOUNT_DIR"
      APP_SOURCE="$(find "$MOUNT_DIR" -maxdepth 1 -name '*.app' -print -quit)"
      [ -n "$APP_SOURCE" ] || { echo "Desktop DMG contains no application." >&2; exit 1; }
      rm -rf "$APP_DIR/RunMat.app"
      cp -R "$APP_SOURCE" "$APP_DIR/RunMat.app"
      hdiutil detach "$MOUNT_DIR" -quiet
      MOUNT_DIR=""
      ;;
    linux/appimage)
      mkdir -p "$APP_DIR"
      cp "$DESKTOP_PACKAGE" "$APP_DIR/runmat-desktop"
      chmod +x "$APP_DIR/runmat-desktop"
      ;;
    *) echo "Unsupported Desktop package kind for this installer: $OS/$DESKTOP_KIND" >&2; exit 1 ;;
  esac
fi

if [ "$INCLUDE_DESKTOP_AND_AGENT" -eq 1 ]; then
  case "$OS" in
    darwin) STATE_DIR="$HOME/Library/Application Support/com.runmat.desktop" ;;
    *) STATE_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/com.runmat.desktop" ;;
  esac
  mkdir -p "$STATE_DIR"
  cp "$TEMP_DIR/tools/cli-tools-state.json" "$STATE_DIR/cli-tools-state.json"
fi

"$BIN_DIR/runmat" --version
if [ "$INCLUDE_DESKTOP_AND_AGENT" -eq 1 ]; then "$BIN_DIR/runmat-agent" --version; fi
echo "RunMat $VERSION installed successfully."
