#!/bin/bash
# Downloads and installs Echo into /Applications.
#
#   curl -fsSL https://echo.franklinokolie.com/install.sh | bash
#
# To install a disk image you've already downloaded instead:
#
#   curl -fsSL https://echo.franklinokolie.com/install.sh | bash -s -- /path/to/Echo-1.0.0-arm64.dmg
#
# What it does, step by step:
#   1. Checks you're on macOS 15 or later, and picks the Apple silicon or Intel version for this Mac.
#   2. Downloads it from this website (unless you gave a disk image), and checks its SHA-256 against the
#      published release.json, so you know it's an untouched release.
#   3. Quits Echo if it's running, and copies Echo.app into /Applications (replacing an older copy).
#   4. Removes the download "quarantine" flag from Echo.app only, so macOS doesn't block it on first launch.
#      (Echo isn't notarized by Apple yet.) Nothing else on your Mac is changed.
#   5. Opens Echo. Its setup guide asks for Input Monitoring.
#
# Everything runs inside main(), so a partly downloaded script does nothing.
set -euo pipefail

SITE="https://echo.franklinokolie.com"
APP="/Applications/Echo.app"
TMP=""
MOUNT=""

bold() { printf '\033[1m%s\033[0m\n' "$*"; }
fail() { printf '\033[31mError:\033[0m %s\n' "$*" >&2; exit 1; }

main() {
  [ "$(uname -s)" = "Darwin" ] || fail "Echo is a macOS app."

  TMP="$(mktemp -d)"
  trap '[ -n "$MOUNT" ] && hdiutil detach -quiet "$MOUNT" 2>/dev/null; rm -rf "$TMP"' EXIT

  curl -fsSL "$SITE/release.json" -o "$TMP/release.json" || fail "Couldn't reach $SITE."
  local version min_macos
  version="$(plutil -extract version raw -o - "$TMP/release.json")"
  min_macos="$(plutil -extract minimumMacOS raw -o - "$TMP/release.json")"

  local have_major need_major
  have_major="$(sw_vers -productVersion | cut -d. -f1)"
  need_major="${min_macos%%.*}"
  [ "$have_major" -ge "$need_major" ] || fail "Echo needs macOS $need_major or later (this Mac has $(sw_vers -productVersion))."

  # Apple silicon, also when this script itself runs under Rosetta.
  local native="x64"
  if [ "$(uname -m)" = "arm64" ] || [ "$(sysctl -in sysctl.proc_translated 2>/dev/null)" = "1" ]; then native="arm64"; fi

  local dmg="${1:-}"
  if [ -z "$dmg" ]; then
    local file
    file="$(plutil -extract "files.$native.file" raw -o - "$TMP/release.json")"
    bold "Downloading Echo $version ($([ "$native" = arm64 ] && echo "Apple silicon" || echo Intel))…"
    dmg="$TMP/$file"
    curl -fL --progress-bar "$SITE/downloads/$file" -o "$dmg" || fail "The download didn't finish. Try again."
  fi
  [ -f "$dmg" ] || fail "$dmg doesn't exist."

  bold "Checking $(basename "$dmg")…"
  local sha arch=""
  sha="$(shasum -a 256 "$dmg" | awk '{print $1}')"
  for candidate in arm64 x64; do
    [ "$sha" = "$(plutil -extract "files.$candidate.sha256" raw -o - "$TMP/release.json")" ] && arch="$candidate"
  done
  [ -n "$arch" ] || fail "This disk image doesn't match Echo $version. Download it again from $SITE."
  [ "$arch" = arm64 ] && [ "$native" = x64 ] && fail "This is the Apple silicon version, and this Mac has an Intel processor."

  MOUNT="$(hdiutil attach -nobrowse -readonly -noautoopen "$dmg" | awk -F'\t' '/\/Volumes\//{print $NF}')"
  [ -d "$MOUNT/Echo.app" ] || fail "Echo.app wasn't found in the disk image."

  if pgrep -xq Echo; then
    bold "Quitting the running Echo…"
    osascript -e 'quit app id "dev.edil.Echo"' >/dev/null 2>&1 || true
    sleep 1
    pkill -x Echo 2>/dev/null || true
  fi

  bold "Installing Echo $version to /Applications…"
  # Admin accounts can write to /Applications; anyone else is asked for an admin password.
  local sudo=""
  [ -w /Applications ] || sudo="sudo"
  $sudo rm -rf "$APP"
  $sudo ditto "$MOUNT/Echo.app" "$APP"
  $sudo xattr -dr com.apple.quarantine "$APP" 2>/dev/null || true

  bold "Done. Opening Echo…"
  open "$APP"
  echo "Look for Echo in your menu bar. Its setup guide asks for Input Monitoring; then start typing."
}

main "$@"
