#!/bin/bash
# SimWin installer for macOS.
#
#   curl -fsSL https://simwin.dev/install.sh | bash
#
# Downloads SimWin.dmg from simwin.dev, checks its SHA-256 and that it is signed by Codeaamy Private Limited
# and notarized by Apple, installs SimWin.app into /Applications (or ~/Applications), puts `simwin` on your
# PATH, and runs `simwin setup` (build tools, Windows environment, IDE device).
#
# Options (pass them after `bash -s --`, e.g. `curl -fsSL https://simwin.dev/install.sh | bash -s -- --no-setup`):
#   --no-setup    install the app and the command only; set up later in the app or with `simwin setup`
#   --no-cli      don't link `simwin` into /usr/local/bin or ~/.local/bin
#   --uninstall   remove SimWin: the IDE device, the app, the `simwin` links and SimWin's folders in ~/Library
#
# Never asks for a password and never uses sudo.
set -euo pipefail

BASE_URL="${SIMWIN_BASE_URL:-https://simwin.dev/download}"
TEAM_ID="Z454JJQAC4"   # Developer ID Application: Codeaamy Private Limited
BUNDLE_ID="com.codeaamy.simwin"

SETUP=1
LINK_CLI=1
UNINSTALL=0
for arg in "$@"; do
  case "$arg" in
    --no-setup) SETUP=0 ;;
    --no-cli) LINK_CLI=0 ;;
    --uninstall) UNINSTALL=1 ;;
    -h|--help) echo "Usage: curl -fsSL https://simwin.dev/install.sh | bash [-s -- --no-setup | --no-cli | --uninstall]"; exit 0 ;;
    *) echo "Unknown option: $arg (use --no-setup, --no-cli or --uninstall)" >&2; exit 2 ;;
  esac
done

if [ -t 1 ]; then BOLD=$'\033[1m'; BLUE=$'\033[34m'; GREEN=$'\033[32m'; RED=$'\033[31m'; RESET=$'\033[0m'
else BOLD=""; BLUE=""; GREEN=""; RED=""; RESET=""; fi
step() { printf '%s==>%s %s%s%s\n' "$BLUE" "$RESET" "$BOLD" "$*" "$RESET"; }
ok()   { printf '%s✓%s %s\n' "$GREEN" "$RESET" "$*"; }
fail() { printf '%serror:%s %s\n' "$RED" "$RESET" "$*" >&2; exit 1; }

# ---- checks ----------------------------------------------------------------------------------------
[ "$(uname -s)" = "Darwin" ] || fail "SimWin runs on macOS only."
MACOS="$(sw_vers -productVersion)"
[ "${MACOS%%.*}" -ge 14 ] || fail "SimWin needs macOS 14 Sonoma or later (this Mac has $MACOS)."
for tool in curl hdiutil ditto codesign shasum; do
  command -v "$tool" >/dev/null || fail "'$tool' is missing."
done

quit_app() {
  if pgrep -x SimWin >/dev/null 2>&1; then
    step "Quitting SimWin"
    osascript -e "tell application id \"$BUNDLE_ID\" to quit" >/dev/null 2>&1 || true
    for _ in $(seq 1 20); do pgrep -x SimWin >/dev/null 2>&1 || break; sleep 0.5; done
    pgrep -x SimWin >/dev/null 2>&1 && fail "SimWin is still running. Quit it (menu bar icon ▸ Quit SimWin) and run this again."
  fi
}

installed_app() {
  for dir in "${SIMWIN_APP_DIR:-/Applications}" "$HOME/Applications"; do
    [ -d "$dir/SimWin.app" ] && { echo "$dir/SimWin.app"; return; }
  done
}

# ---- uninstall -------------------------------------------------------------------------------------
if [ "$UNINSTALL" = 1 ]; then
  APP="$(installed_app || true)"
  if [ -n "$APP" ] && [ -x "$APP/Contents/Helpers/simwin" ]; then
    "$APP/Contents/Helpers/simwin" setup --unregister || true
  fi
  quit_app
  [ -n "$APP" ] && { rm -rf "$APP"; ok "Removed $APP"; }
  for link in /usr/local/bin/simwin "$HOME/.local/bin/simwin"; do
    if [ -L "$link" ] && [[ "$(readlink "$link")" == *"SimWin.app"* ]]; then
      if rm -f "$link" 2>/dev/null; then ok "Removed $link"; else echo "   Remove $link yourself (it needs an administrator): sudo rm $link"; fi
    fi
  done
  for dir in "$HOME/Library/Application Support/SimWin" "$HOME/Library/Caches/SimWin" "$HOME/Library/Logs/SimWin"; do
    [ -d "$dir" ] && { rm -rf "$dir"; ok "Removed $dir"; }
  done
  echo "SimWin is uninstalled."
  exit 0
fi

# ---- download and verify ---------------------------------------------------------------------------
WORK="$(mktemp -d "${TMPDIR:-/tmp}/simwin-install.XXXXXX")"
MOUNT="$WORK/mnt"
cleanup() {
  [ -d "$MOUNT" ] && hdiutil detach "$MOUNT" -quiet >/dev/null 2>&1 || true
  rm -rf "$WORK"
}
trap cleanup EXIT

step "Downloading SimWin"
curl -fL --progress-bar -o "$WORK/SimWin.dmg" "$BASE_URL/SimWin.dmg" || fail "Couldn't download $BASE_URL/SimWin.dmg."
curl -fsSL -o "$WORK/SimWin.dmg.sha256" "$BASE_URL/SimWin.dmg.sha256" || fail "Couldn't download the checksum."
EXPECTED="$(awk '{print $1}' "$WORK/SimWin.dmg.sha256")"
ACTUAL="$(shasum -a 256 "$WORK/SimWin.dmg" | awk '{print $1}')"
[ -n "$EXPECTED" ] && [ "$EXPECTED" = "$ACTUAL" ] || fail "The download is damaged (SHA-256 mismatch). Please try again."
ok "Checksum verified"

mkdir -p "$MOUNT"
hdiutil attach -nobrowse -readonly -noautoopen -mountpoint "$MOUNT" "$WORK/SimWin.dmg" >/dev/null || fail "Couldn't open SimWin.dmg."
SOURCE="$MOUNT/SimWin.app"
[ -d "$SOURCE" ] || fail "SimWin.app is not in the disk image."
codesign --verify --deep --strict "$SOURCE" 2>/dev/null || fail "SimWin.app's signature is not valid."
# Captured first: with pipefail, `grep -q` exiting early would SIGPIPE codesign and fail the check.
SIGNATURE="$(codesign -dv "$SOURCE" 2>&1)"
grep -qx "TeamIdentifier=$TEAM_ID" <<<"$SIGNATURE" || fail "SimWin.app is not signed by Codeaamy Private Limited."
spctl -a -t exec "$SOURCE" >/dev/null 2>&1 || fail "SimWin.app is not notarized by Apple."
VERSION="$(/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' "$SOURCE/Contents/Info.plist")"
ok "SimWin $VERSION, signed by Codeaamy Private Limited and notarized by Apple"

# ---- install the app -------------------------------------------------------------------------------
APP_DIR="${SIMWIN_APP_DIR:-/Applications}"
if [ ! -w "$APP_DIR" ]; then
  APP_DIR="$HOME/Applications"
  mkdir -p "$APP_DIR"
fi
APP="$APP_DIR/SimWin.app"
quit_app
step "Installing to $APP"
OTHER="$(installed_app || true)"
[ -n "$OTHER" ] && [ "$OTHER" != "$APP" ] && rm -rf "$OTHER"
rm -rf "$APP"
ditto "$SOURCE" "$APP"
ok "Installed SimWin $VERSION"
CLI="$APP/Contents/Helpers/simwin"

# ---- the simwin command -----------------------------------------------------------------------------
if [ "$LINK_CLI" = 1 ]; then
  if [ -d /usr/local/bin ] && [ -w /usr/local/bin ]; then BIN=/usr/local/bin; else BIN="$HOME/.local/bin"; mkdir -p "$BIN"; fi
  ln -sf "$CLI" "$BIN/simwin"
  ok "Linked $BIN/simwin"
  case ":$PATH:" in
    *":$BIN:"*) ;;
    *) echo "   $BIN is not on your PATH. Add it with:"
       echo "     echo 'export PATH=\"$BIN:\$PATH\"' >> ~/.zshrc && source ~/.zshrc" ;;
  esac
fi

# ---- setup ------------------------------------------------------------------------------------------
if [ "$SETUP" = 1 ]; then
  if ! command -v flutter >/dev/null 2>&1 && [ ! -x "$HOME/development/flutter/bin/flutter" ] && [ ! -x "$HOME/flutter/bin/flutter" ]; then
    echo
    echo "Flutter wasn't found, so setup is left for later. Install Flutter (https://docs.flutter.dev/get-started),"
    echo "then run: simwin setup   (or open SimWin, which walks you through it)."
    exit 0
  fi
  step "Setting up (build tools, Windows environment, IDE device; about 400 MB the first time)"
  if ! "$CLI" setup; then
    echo
    echo "Setup didn't finish. Fix the problem above, then run: simwin setup   (or open SimWin)."
    exit 1
  fi
fi

echo
ok "${BOLD}SimWin is ready.${RESET}"
if [ "$SETUP" = 1 ]; then
  echo "   Open a Flutter project in VS Code or Android Studio and pick \"SimWin · Windows 11\","
  echo "   or run: flutter run -d simwin"
else
  echo "   Open SimWin (or run: simwin setup) to finish setting up."
fi
echo "   Guide: https://simwin.dev/install/   Problems: simwin report, or https://simwin.dev/support/"
