#!/bin/bash
# THE Note installer · GPL-3.0-or-later · https://github.com/tobwil/THENote
# No sudo, no automatic launch, no change to macOS security settings.
set -euo pipefail

# BEGIN RELEASE (generated by scripts/sync-distribution.mjs)
VERSION='0.2.6'
ARCHIVE='THE.Note-macOS-arm64.zip'
SHA256='c3b2541e4ed43c681374fd1380ce3ea411d7d040aad059d1e26224d6f7409e63'
DOWNLOAD='https://github.com/tobwil/THENote/releases/download/v0.2.6/THE.Note-macOS-arm64.zip'
NOTARIZED='true'
SIGNING_NOTICE='This is a preview for Apple Silicon, Developer ID signed and Apple-notarized.'
# END RELEASE

app_dir="${HOME}/Applications"
check_only=false
replace=false
local_archive=''
work=''
stage=''
backup=''
destination=''
fail() { printf 'THE Note: %s\n' "$*" >&2; exit 1; }
usage() {
  cat <<'HELP'
THE Note · macOS Apple Silicon installer

Usage: bash install.sh [--check] [--replace] [--app-dir /absolute/path]
                      [--archive /path/to/release.zip]

Default: ~/Applications/THE Note.app, without sudo.
--check       Download and verify only; do not install or replace anything.
--replace     Replace an existing, closed THE Note. Keep a backup beside it.
--app-dir     Choose an absolute installation directory.
--archive     Verify/install a local copy of this exact release instead of downloading.
--help        Show this help.

HELP
  printf '%s Security settings are left intact.\n' "$SIGNING_NOTICE"
}
while [ "$#" -gt 0 ]; do
  case "$1" in
    --check) check_only=true; shift ;;
    --replace) replace=true; shift ;;
    --app-dir|--archive)
      option="$1"; [ "$#" -ge 2 ] || fail "Missing value for $option"
      case "$option" in --app-dir) app_dir="$2" ;; --archive) local_archive="$2" ;; esac
      shift 2 ;;
    --help|-h) usage; exit 0 ;;
    *) fail "Unknown argument: $1 (use --help)" ;;
  esac
done
[ "$(uname -s)" = Darwin ] || fail 'This release supports macOS only.'
[ "$(uname -m)" = arm64 ] || fail 'This release requires native Apple Silicon (arm64). On an Apple Silicon Mac, use a terminal outside Rosetta.'
os_major="$(/usr/bin/sw_vers -productVersion | cut -d. -f1)"
[ "$os_major" -ge 11 ] || fail 'macOS 11 or newer is required.'
case "$app_dir" in /*) ;; *) fail '--app-dir must be an absolute path.' ;; esac
[ "$app_dir" != / ] || fail 'Choose an application directory, not the filesystem root.'
destination="$app_dir/THE Note.app"
if ! $check_only; then
  if /usr/bin/pgrep -x the-note >/dev/null; then fail 'THE Note is running. Save your notes and quit it before installing.'; fi
  [ ! -L "$destination" ] || fail 'The destination is a symlink. Use its package manager or choose another directory.'
  if [ -e "$destination" ] && ! $replace; then fail 'THE Note already exists. Use --replace after closing it, or choose another --app-dir.'; fi
fi
cleanup() {
  status=$?
  if [ -n "$backup" ] && [ -e "$backup" ] && [ ! -e "$destination" ]; then
    /bin/mv "$backup" "$destination" || printf 'Restore your previous app from: %s\n' "$backup" >&2
  fi
  if [ -n "$stage" ] && [ -d "$stage" ]; then /bin/rm -rf "$stage"; fi
  if [ -n "$work" ] && [ -d "$work" ]; then /bin/rm -rf "$work"; fi
  exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
work="$(/usr/bin/mktemp -d "${TMPDIR:-/tmp}/the-note-download.XXXXXX")"
printf 'THE Note %s · macOS Apple Silicon\n' "$VERSION"
if [ -n "$local_archive" ]; then
  [ -f "$local_archive" ] || fail 'The local archive does not exist.'
  /bin/cp "$local_archive" "$work/$ARCHIVE"
else
  /usr/bin/curl --fail --location --show-error --proto '=https' --tlsv1.2 --connect-timeout 20 --max-time 300 --retry 2 "$DOWNLOAD" -o "$work/$ARCHIVE"
fi
actual="$(/usr/bin/shasum -a 256 "$work/$ARCHIVE" | /usr/bin/awk '{print $1}')"
[ "$actual" = "$SHA256" ] || fail 'Checksum mismatch. Nothing has been installed.'
/usr/bin/ditto -x -k "$work/$ARCHIVE" "$work/unpacked"
app="$work/unpacked/THE Note.app"
[ -d "$app" ] || fail 'The verified archive has no THE Note.app bundle.'
/usr/bin/codesign --verify --deep --strict "$app" || fail 'App signature verification failed.'
if [ "$NOTARIZED" = true ]; then
  /usr/sbin/spctl --assess --type execute --verbose=2 "$app" || fail 'Apple notarization/Gatekeeper verification failed.'
fi
[ "$(/usr/libexec/PlistBuddy -c 'Print CFBundleIdentifier' "$app/Contents/Info.plist")" = app.thenote.desktop ] || fail 'Unexpected bundle identifier.'
[ "$(/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' "$app/Contents/Info.plist")" = "$VERSION" ] || fail 'Unexpected app version.'
if $check_only; then printf 'SHA-256, app signature, identifier and version verified. No installation performed.\n'; exit 0; fi
/bin/mkdir -p "$app_dir"
[ -w "$app_dir" ] || fail "No write permission for $app_dir. Choose a user-owned directory."
stage="$(/usr/bin/mktemp -d "$app_dir/.the-note-install.XXXXXX")"
/usr/bin/ditto "$app" "$stage/THE Note.app"
/usr/bin/codesign --verify --deep --strict "$stage/THE Note.app"
if /usr/bin/pgrep -x the-note >/dev/null; then fail 'THE Note started while downloading. Close it and try again.'; fi
if [ -e "$destination" ]; then
  $replace || fail 'The destination appeared during download. Nothing replaced.'
  [ ! -L "$destination" ] || fail 'The destination became a symlink. Nothing replaced.'
  # Refuse to replace an unrelated bundle even if it happens to share the name.
  [ "$(/usr/libexec/PlistBuddy -c 'Print CFBundleIdentifier' "$destination/Contents/Info.plist" 2>/dev/null)" = app.thenote.desktop ] || fail 'The existing app has an unexpected identifier.'
  backup="$app_dir/.THE Note-backup-$(/bin/date +%Y%m%d-%H%M%S)-$$.app"
  /bin/mv "$destination" "$backup"
fi
/bin/mv "$stage/THE Note.app" "$destination"
printf '\nInstalled: %s\n' "$destination"
if [ -n "$backup" ]; then printf 'Previous app retained at: %s\n' "$backup"; fi
printf 'Open it in Finder when ready. %s\n' "$SIGNING_NOTICE"
if [ "$NOTARIZED" != true ]; then
  printf 'If macOS blocks opening, review it under System Settings → Privacy & Security.\n'
fi
