#!/bin/sh
# Darwin installer for macOS.
#
#   curl -fsSL https://rundarwin.com/install.sh | sh
#
# Darwin isn't notarised by Apple yet, so a copy downloaded in a browser is stopped by
# Gatekeeper the first time it opens. A download made with curl isn't marked as coming from
# the internet, so the copy this script installs opens straight away. What it does:
#
#   1. reads the latest release from https://downloads.rundarwin.com/darwin/latest.json;
#   2. downloads Darwin.app (one build for Apple Silicon and Intel);
#   3. checks its SHA-256 against the one in latest.json;
#   4. quits a running Darwin and puts the new app in /Applications (or ~/Applications),
#      keeping the old one until the new one is in place;
#   5. opens it.
#
# Your terminals and agents keep running through an update: they live in Darwin's engine,
# not in the app window.
#
# Environment variables:
#   DARWIN_APP_DIR   Where to put Darwin.app. Default: /Applications if writable, else ~/Applications.
#   DARWIN_NO_OPEN   Set to 1 to skip opening Darwin afterwards.

set -eu

BASE="https://downloads.rundarwin.com/darwin"

say()  { printf '\033[38;5;208m→\033[0m %s\n' "$1"; }
die()  { printf '\033[31mx\033[0m %s\n' "$1" >&2; exit 1; }

[ "$(uname -s)" = "Darwin" ] || die "This installer is for macOS."
major=$(sw_vers -productVersion | cut -d. -f1)
[ "$major" -ge 11 ] 2>/dev/null || die "Darwin needs macOS 11 or newer (this Mac has $(sw_vers -productVersion))."
for t in curl tar shasum plutil ditto; do
  command -v "$t" >/dev/null 2>&1 || die "Missing '$t', which comes with macOS."
done

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT INT TERM

say "Finding the latest Darwin"
curl -fsSL "$BASE/latest.json" -o "$tmp/latest.json" || die "Couldn't reach downloads.rundarwin.com."
field() { plutil -extract "$1" raw -o - "$tmp/latest.json" 2>/dev/null || die "latest.json has no '$1'."; }
version=$(field version)
app_url=$(field app.url)
app_sha=$(field app.sha256)

say "Downloading Darwin $version"
curl -fL --progress-bar "$app_url" -o "$tmp/Darwin.app.tar.gz" || die "The download failed."

say "Checking the download"
got=$(shasum -a 256 "$tmp/Darwin.app.tar.gz" | cut -d' ' -f1)
[ "$got" = "$app_sha" ] || die "Checksum mismatch: expected $app_sha, got $got. Nothing was installed."
tar -xzf "$tmp/Darwin.app.tar.gz" -C "$tmp"
[ -d "$tmp/Darwin.app" ] || die "The download didn't contain Darwin.app."

dest="${DARWIN_APP_DIR:-}"
if [ -z "$dest" ]; then
  if [ -w /Applications ]; then dest=/Applications; else dest="$HOME/Applications"; fi
fi
mkdir -p "$dest"

if [ "$(osascript -e 'application id "com.ekpyros.darwin" is running' 2>/dev/null)" = "true" ]; then
  say "Quitting Darwin (your terminals and agents keep running)"
  osascript -e 'quit app "Darwin"' >/dev/null 2>&1 || true
  sleep 2
fi

say "Installing to $dest/Darwin.app"
if [ -d "$dest/Darwin.app" ]; then
  mv "$dest/Darwin.app" "$tmp/Darwin.old.app"
fi
if ! ditto "$tmp/Darwin.app" "$dest/Darwin.app"; then
  [ -d "$tmp/Darwin.old.app" ] && mv "$tmp/Darwin.old.app" "$dest/Darwin.app"
  die "Couldn't write to $dest. Try DARWIN_APP_DIR=\$HOME/Applications."
fi

printf '\033[32m✓\033[0m Darwin %s is installed.\n' "$version"
if [ "${DARWIN_NO_OPEN:-0}" != "1" ]; then
  open "$dest/Darwin.app"
fi
