#!/usr/bin/env bash
set -euo pipefail

readonly VOICE_VERSION="2.1.13"
readonly MINECRAFT_VERSION="26.2"
readonly VOICE_FILE="plasmovoice-fabric-26.2-2.1.13.jar"
readonly VOICE_URL="https://github.com/plasmoapp/plasmo-voice/releases/download/2.1.13/$VOICE_FILE"
readonly VOICE_SHA256="108a3a56647ed9fd4673f8788b4a3bb42bd12925db2dd280196290f569a20b82"

instance_dir=""

usage() {
  cat <<'EOF'
Usage: osdcraft-setup-macos.sh [--instance PATH]

Installs the verified Plasmo Voice Fabric client mod into a FreeSM,
Prism Launcher, or MultiMC Minecraft 26.2 instance on macOS. Existing
Plasmo Voice JARs are moved into a timestamped backup directory.
EOF
}

file_sha256() {
  if command -v shasum >/dev/null 2>&1; then
    shasum -a 256 "$1" | awk '{print $1}'
  elif command -v sha256sum >/dev/null 2>&1; then
    sha256sum "$1" | awk '{print $1}'
  else
    echo "A SHA-256 utility is required (shasum or sha256sum)." >&2
    return 1
  fi
}

while (( $# )); do
  case "$1" in
    --instance)
      [[ $# -ge 2 ]] || { echo "Missing path after --instance" >&2; exit 2; }
      instance_dir=${2%/}
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown option: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

echo "OSDCraft client setup for macOS"
echo "Minecraft: $MINECRAFT_VERSION | Plasmo Voice: $VOICE_VERSION"
echo

candidates=()

add_candidate() {
  local candidate=$1
  local existing
  [[ -f "$candidate/instance.cfg" ]] || return 0
  for existing in "${candidates[@]}"; do
    [[ $existing != "$candidate" ]] || return 0
  done
  candidates+=("$candidate")
}

if [[ -z $instance_dir ]]; then
  roots=(
    "$HOME/Library/Application Support/PrismLauncher/instances"
    "$HOME/Library/Application Support/FreesmLauncher/instances"
    "$HOME/Library/Application Support/FreeSMLauncher/instances"
    "$HOME/Library/Application Support/freesm-launcher/instances"
    "$HOME/Library/Application Support/multimc/instances"
  )

  for root in "${roots[@]}"; do
    [[ -d $root ]] || continue
    for candidate in "$root"/*; do
      [[ -d $candidate ]] || continue
      add_candidate "$candidate"
    done
  done

  if (( ${#candidates[@]} == 1 )); then
    instance_dir=${candidates[0]}
  elif (( ${#candidates[@]} > 1 )); then
    echo "Select your Minecraft 26.2 instance:"
    for index in "${!candidates[@]}"; do
      name=$(awk -F= '$1 == "name" { sub(/^[^=]*=/, ""); print; exit }' "${candidates[$index]}/instance.cfg")
      printf '  %d) %s\n' "$((index + 1))" "${name:-${candidates[$index]##*/}}"
    done
    read -r -p "Instance number: " selection </dev/tty
    [[ $selection =~ ^[0-9]+$ ]] || { echo "Invalid selection" >&2; exit 2; }
    (( selection >= 1 && selection <= ${#candidates[@]} )) || { echo "Selection out of range" >&2; exit 2; }
    instance_dir=${candidates[$((selection - 1))]}
  else
    read -r -p "Paste the FreeSM/Prism/MultiMC instance directory: " instance_dir </dev/tty
    instance_dir=${instance_dir%/}
  fi
fi

[[ -d $instance_dir ]] || { echo "Instance directory not found: $instance_dir" >&2; exit 1; }
[[ -f "$instance_dir/instance.cfg" ]] || { echo "instance.cfg not found in: $instance_dir" >&2; exit 1; }

pack_file="$instance_dir/mmc-pack.json"
[[ -f $pack_file ]] || { echo "mmc-pack.json not found in: $instance_dir" >&2; exit 1; }

detected_version=""
if command -v python3 >/dev/null 2>&1; then
  detected_version=$(python3 - "$pack_file" <<'PY'
import json
import sys

with open(sys.argv[1], encoding="utf-8") as handle:
    data = json.load(handle)

for component in data.get("components", []):
    if component.get("uid") == "net.minecraft":
        print(component.get("version", ""))
        break
PY
  )
else
  detected_version=$(grep -oE '"version"[[:space:]]*:[[:space:]]*"26\.2"' "$pack_file" | head -n1 | grep -o '26\.2' || true)
fi

if [[ $detected_version != "$MINECRAFT_VERSION" ]]; then
  echo "This installer requires a Minecraft $MINECRAFT_VERSION instance." >&2
  echo "Detected version: ${detected_version:-unknown}" >&2
  exit 1
fi

mods_dir="$instance_dir/.minecraft/mods"
mkdir -p "$mods_dir"

if [[ -f "$mods_dir/$VOICE_FILE" ]]; then
  current_hash=$(file_sha256 "$mods_dir/$VOICE_FILE")
  if [[ $current_hash == "$VOICE_SHA256" ]]; then
    echo "Plasmo Voice $VOICE_VERSION is already installed and verified."
    echo "Server: mc.jpoop.in | Open voice settings with V"
    exit 0
  fi
fi

temp_file=$(mktemp -t osdcraft-voice.XXXXXX)
trap 'rm -f "$temp_file"' EXIT

curl -fL --retry 3 --connect-timeout 15 "$VOICE_URL" -o "$temp_file"

download_hash=$(file_sha256 "$temp_file")
if [[ $download_hash != "$VOICE_SHA256" ]]; then
  echo "Checksum verification failed. Nothing was installed." >&2
  echo "Expected: $VOICE_SHA256" >&2
  echo "Received: $download_hash" >&2
  exit 1
fi

timestamp=$(date -u +%Y%m%dT%H%M%SZ)
backup_dir="$mods_dir/osdcraft-backup-$timestamp"
shopt -s nullglob
old_jars=("$mods_dir"/plasmovoice-fabric-*.jar)
shopt -u nullglob
if (( ${#old_jars[@]} )); then
  mkdir -p "$backup_dir"
  mv -- "${old_jars[@]}" "$backup_dir/"
  echo "Moved ${#old_jars[@]} previous Plasmo Voice JAR(s) to: $backup_dir"
fi

install -m 0644 "$temp_file" "$mods_dir/$VOICE_FILE"
trap - EXIT
rm -f "$temp_file"

cat <<EOF

Installation complete.
Instance: $instance_dir
Installed: $VOICE_FILE
Checksum: $VOICE_SHA256

Next:
  1. Restart the launcher instance.
  2. Join mc.jpoop.in.
  3. Press V to select your microphone and output device.
EOF
