#!/bin/bash
# Mix Checker plugin installer - macOS universal (Apple Silicon + Intel)
set -euo pipefail

DOWNLOAD_URL="${MIXCHECKER_DOWNLOAD_URL:-https://mixchecker.in/downloads/MixChecker-macOS.zip}"
USER_PLUGIN_ROOT="${MIXCHECKER_USER_PLUGIN_ROOT:-$HOME/Library/Audio/Plug-Ins}"
SYSTEM_PLUGIN_ROOT="${MIXCHECKER_SYSTEM_PLUGIN_ROOT:-/Library/Audio/Plug-Ins}"
VST3_DIR="$USER_PLUGIN_ROOT/VST3"
AU_DIR="$USER_PLUGIN_ROOT/Components"
VST3_DEST="$VST3_DIR/MixChecker.vst3"
AU_DEST="$AU_DIR/MixChecker.component"
SYSTEM_VST3="$SYSTEM_PLUGIN_ROOT/VST3/MixChecker.vst3"
SYSTEM_AU="$SYSTEM_PLUGIN_ROOT/Components/MixChecker.component"
FIREWALL_TOOL="${MIXCHECKER_FIREWALL_TOOL:-/usr/libexec/ApplicationFirewall/socketfilterfw}"

say()  { printf '%s\n' "$*"; }
warn() { printf 'WARNING: %s\n' "$*" >&2; }
fail() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }

case "$VST3_DEST" in
  */Library/Audio/Plug-Ins/VST3/MixChecker.vst3) ;;
  *) fail "refusing unsafe VST3 destination: $VST3_DEST" ;;
esac
case "$AU_DEST" in
  */Library/Audio/Plug-Ins/Components/MixChecker.component) ;;
  *) fail "refusing unsafe AU destination: $AU_DEST" ;;
esac

TMP="$(mktemp -d "${TMPDIR:-/tmp}/mixchecker-install.XXXXXX")"
cleanup() {
  /bin/rm -rf "$TMP"
  if [[ "$0" == *.command ]] && [ -r /dev/tty ]; then
    echo
    read -r -p "Press Return to close this window..." _ </dev/tty || true
  fi
}
trap cleanup EXIT

remove_legacy_system_copy() {
  local target="$1"
  local parent

  if [ ! -e "$target" ] && [ ! -L "$target" ]; then
    return
  fi

  say "Found an older system-wide copy:"
  say "  $target"
  parent="$(/usr/bin/dirname "$target")"

  if [ -w "$parent" ]; then
    /bin/rm -rf "$target"
  else
    say "Administrator permission is required to remove the older copy."
    /usr/bin/sudo /bin/rm -rf "$target" \
      || fail "could not remove the older system-wide copy: $target"
  fi

  if [ -e "$target" ] || [ -L "$target" ]; then
    fail "older system-wide copy still exists: $target"
  fi
}

discover_daw_executables() {
  local roots=()
  local app
  local executable_name
  local executable_path

  DAW_EXECUTABLES=()
  [ -d "/Applications" ] && roots+=("/Applications")
  [ -d "$HOME/Applications" ] && roots+=("$HOME/Applications")
  [ "${#roots[@]}" -gt 0 ] || return

  while IFS= read -r -d '' app; do
    executable_name="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$app/Contents/Info.plist" 2>/dev/null || true)"
    [ -n "$executable_name" ] || continue
    executable_path="$app/Contents/MacOS/$executable_name"
    [ -f "$executable_path" ] || continue
    DAW_EXECUTABLES+=("$executable_path")
  done < <(
    /usr/bin/find "${roots[@]}" -maxdepth 2 -type d \
      \( -name 'Logic Pro.app' \
      -o -name 'GarageBand.app' \
      -o -name 'FL Studio*.app' \
      -o -name 'Ableton Live*.app' \
      -o -name 'REAPER*.app' \
      -o -name 'Cubase*.app' \
      -o -name 'Studio One*.app' \
      -o -name 'Pro Tools.app' \
      -o -name 'Bitwig Studio.app' \
      -o -name 'Reason*.app' \
      -o -name 'Digital Performer*.app' \
      -o -name 'Waveform*.app' \
      -o -name 'LUNA.app' \) \
      -prune -print0 2>/dev/null
  )
}

configure_application_firewall() {
  local firewall_state
  local block_all_state
  local answer
  local executable_path
  local failed=0

  if [ "${MIXCHECKER_SKIP_FIREWALL:-0}" = "1" ]; then
    say "Skipping macOS firewall configuration."
    return
  fi

  [ -x "$FIREWALL_TOOL" ] || {
    warn "macOS Application Firewall tool was not found; DAW access was not changed."
    return
  }

  firewall_state="$("$FIREWALL_TOOL" --getglobalstate 2>/dev/null || true)"
  case "$firewall_state" in
    *"State = 1"*|*"enabled"*) ;;
    *)
      say "macOS Application Firewall is disabled; no DAW firewall changes are needed."
      return
      ;;
  esac

  discover_daw_executables
  if [ "${#DAW_EXECUTABLES[@]}" -eq 0 ]; then
    warn "macOS Firewall is enabled, but no supported DAW was found in Applications."
    warn "If the phone cannot connect, allow your DAW in System Settings > Network > Firewall > Options."
    return
  fi

  say ""
  say "macOS Firewall is enabled. Mix Checker receives audio-network requests inside your DAW."
  say "Detected DAW hosts:"
  for executable_path in "${DAW_EXECUTABLES[@]}"; do
    say "  $executable_path"
  done

  if [ "${MIXCHECKER_FIREWALL_DRY_RUN:-0}" = "1" ]; then
    for executable_path in "${DAW_EXECUTABLES[@]}"; do
      say "Firewall dry run - would allow: $executable_path"
    done
    return
  fi

  if [ ! -r /dev/tty ]; then
    warn "No interactive terminal is available; DAW firewall access was not changed."
    return
  fi

  printf 'Allow these DAWs to receive Mix Checker connections? [Y/n] ' >/dev/tty
  IFS= read -r answer </dev/tty || answer="n"
  case "$answer" in
    n|N|no|NO|No)
      say "DAW firewall access was left unchanged."
      return
      ;;
  esac

  /usr/bin/sudo -v || {
    warn "administrator permission was not granted; DAW firewall access was not changed."
    return
  }

  for executable_path in "${DAW_EXECUTABLES[@]}"; do
    /usr/bin/sudo "$FIREWALL_TOOL" --add "$executable_path" >/dev/null 2>&1 || true
    if /usr/bin/sudo "$FIREWALL_TOOL" --unblockapp "$executable_path" >/dev/null 2>&1; then
      say "Allowed through macOS Firewall: $executable_path"
    else
      warn "could not allow this DAW through macOS Firewall: $executable_path"
      failed=1
    fi
  done

  block_all_state="$("$FIREWALL_TOOL" --getblockall 2>/dev/null || true)"
  case "$block_all_state" in
    *"State = 1"*|*"enabled"*)
      warn "Block all incoming connections is enabled. Disable it if Mix Checker cannot connect."
      ;;
  esac

  [ "$failed" -eq 0 ] || warn "one or more DAW firewall entries could not be configured."
}

say "Mix Checker plugin installer"
say "============================="
say ""
say "Downloading Mix Checker..."
curl -fL --progress-bar "$DOWNLOAD_URL" -o "$TMP/MixChecker-macOS.zip" \
  || fail "download failed - check your internet connection"
unzip -tq "$TMP/MixChecker-macOS.zip" >/dev/null \
  || fail "downloaded file is corrupted - please try again"
unzip -q "$TMP/MixChecker-macOS.zip" -d "$TMP"

VST3_SRC="$(/usr/bin/find "$TMP" -maxdepth 3 -type d -name 'MixChecker.vst3' | head -n 1)"
AU_SRC="$(/usr/bin/find "$TMP" -maxdepth 3 -type d -name 'MixChecker.component' | head -n 1)"
[ -n "$VST3_SRC" ] && [ -d "$VST3_SRC/Contents" ] \
  || fail "downloaded archive did not contain a valid MixChecker.vst3"
[ -n "$AU_SRC" ] && [ -d "$AU_SRC/Contents" ] \
  || fail "downloaded archive did not contain a valid MixChecker.component"
[ -f "$VST3_SRC/Contents/MacOS/MixChecker" ] \
  || fail "MixChecker VST3 executable is missing"
[ -f "$AU_SRC/Contents/MacOS/MixChecker" ] \
  || fail "MixChecker AU executable is missing"

VST3_ID="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$VST3_SRC/Contents/Info.plist" 2>/dev/null || true)"
AU_ID="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$AU_SRC/Contents/Info.plist" 2>/dev/null || true)"
VST3_VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$VST3_SRC/Contents/Info.plist" 2>/dev/null || true)"
AU_VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$AU_SRC/Contents/Info.plist" 2>/dev/null || true)"
[ "$VST3_ID" = "com.mixchecker.plugin" ] || fail "unexpected VST3 bundle identifier: $VST3_ID"
[ "$AU_ID" = "com.mixchecker.plugin" ] || fail "unexpected AU bundle identifier: $AU_ID"
[ -n "$VST3_VERSION" ] && [ "$VST3_VERSION" = "$AU_VERSION" ] \
  || fail "VST3 and AU versions do not match"

# Remove exact legacy system-wide bundles before installing per-user copies. This
# prevents DAWs from finding a stale /Library bundle before the new ~/Library bundle.
remove_legacy_system_copy "$SYSTEM_VST3"
remove_legacy_system_copy "$SYSTEM_AU"

mkdir -p "$VST3_DIR" "$AU_DIR"
say "Installing Mix Checker $VST3_VERSION (replacing any previous version)..."
/bin/rm -rf "$VST3_DEST" "$AU_DEST"
/bin/cp -R "$VST3_SRC" "$VST3_DIR/"
/bin/cp -R "$AU_SRC" "$AU_DIR/"

# Clear browser quarantine from the copied bundles. Public release bundles should
# still be Developer ID signed and notarized independently of this installer step.
xattr -cr "$VST3_DEST" 2>/dev/null || true
xattr -cr "$AU_DEST" 2>/dev/null || true

[ -f "$VST3_DEST/Contents/MacOS/MixChecker" ] \
  || fail "VST3 installation verification failed"
[ -f "$AU_DEST/Contents/MacOS/MixChecker" ] \
  || fail "AU installation verification failed"
[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$VST3_DEST/Contents/Info.plist" 2>/dev/null || true)" = "com.mixchecker.plugin" ] \
  || fail "installed VST3 metadata verification failed"
[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$AU_DEST/Contents/Info.plist" 2>/dev/null || true)" = "com.mixchecker.plugin" ] \
  || fail "installed AU metadata verification failed"

configure_application_firewall

say ""
say "Done. Mix Checker $VST3_VERSION is installed:"
say "  VST3: $VST3_DEST"
say "  AU:   $AU_DEST"
say ""
say "Next: open your DAW, rescan plugins, add Mix Checker LAST on the master channel,"
say "then scan the QR code with the Mix Checker Android app."
