#!/usr/bin/env bash
# install.sh — Install MRT2 live-coding externals for Max, Pure Data, and SuperCollider.
#
# Usage:
#   ./install.sh          # Install for all detected programs
#   ./install.sh max      # Install only the Max external
#   ./install.sh pd       # Install only the Pd external
#   ./install.sh sc       # Install only the SC external
#   ./install.sh max pd   # Install Max and Pd only
#
# The script auto-detects installed programs and their version-specific
# extension directories. It will not install for a program that is not found.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
BOLD='\033[1m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
RED='\033[0;31m'
CYAN='\033[0;36m'
RESET='\033[0m'

info()  { echo -e "${CYAN}→${RESET} $*"; }
ok()    { echo -e "${GREEN}✓${RESET} $*"; }
warn()  { echo -e "${YELLOW}⚠${RESET} $*"; }
err()   { echo -e "${RED}✗${RESET} $*" >&2; }

# ─── Max ─────────────────────────────────────────────────────────────────────

install_max() {
    local src="$SCRIPT_DIR/max"
    if [[ ! -d "$src/mrt2~.mxo" ]]; then
        err "Max source files not found in $src"
        return 1
    fi

    local -a targets=()

    # Detect Max versions by checking ~/Documents/Max N/ directories.
    # These are created on first launch of Max (standalone or inside Ableton).
    for version in 7 8 9 10; do
        local docs_dir="$HOME/Documents/Max $version"
        if [[ -d "$docs_dir" ]]; then
            targets+=("$docs_dir/Library")
        fi
    done

    # Also check for future versions via glob
    for d in "$HOME"/Documents/Max\ */; do
        [[ -d "$d" ]] || continue
        local lib="${d}Library"
        # Avoid duplicates
        local already=false
        for t in "${targets[@]+"${targets[@]}"}"; do
            [[ "$t" == "$lib" ]] && already=true
        done
        $already || targets+=("$lib")
    done

    if [[ ${#targets[@]} -eq 0 ]]; then
        warn "No Max installation detected (no ~/Documents/Max N/ found)"
        return 0
    fi

    for target in "${targets[@]}"; do
        info "Installing Max external → ${BOLD}$target${RESET}"
        mkdir -p "$target"

        # Install into a subfolder so the .mxo and help file stay together
        local dest="$target/mrt2~"
        mkdir -p "$dest"

        ditto "$src/mrt2~.mxo" "$dest/mrt2~.mxo"
        cp "$src/mrt2~.maxhelp" "$dest/"

        ok "Max: installed to $dest"
    done
}

# ─── Pure Data ───────────────────────────────────────────────────────────────

install_pd() {
    local src="$SCRIPT_DIR/pd"
    if [[ ! -f "$src/mrt2~.pd_darwin" ]]; then
        err "Pd source files not found in $src"
        return 1
    fi

    # Detect Pd installation
    local pd_found=false

    # Check for any Pd variant in /Applications
    for app in /Applications/Pd*.app /Applications/Purr\ Data*.app; do
        [[ -e "$app" ]] && pd_found=true && break
    done

    # Also check via mdfind (covers non-standard install locations)
    if ! $pd_found; then
        if mdfind "kMDItemCFBundleIdentifier == 'org.puredata.pd.pd-gui'" 2>/dev/null | grep -q "."; then
            pd_found=true
        fi
    fi

    if ! $pd_found; then
        # Even if the app isn't found, the Documents/Pd dir might exist
        if [[ -d "$HOME/Documents/Pd" ]]; then
            pd_found=true
        fi
    fi

    if ! $pd_found; then
        warn "No Pure Data installation detected"
        return 0
    fi

    # Standard user externals path (used by all Pd variants)
    local target="$HOME/Documents/Pd/externals/mrt2~"
    info "Installing Pd external → ${BOLD}$target${RESET}"
    mkdir -p "$target"

    cp "$src/mrt2~.pd_darwin" "$target/"
    cp "$src/mlx.metallib"    "$target/"
    cp "$src/mrt2~-help.pd"   "$target/"

    ok "Pd: installed to $target"
}

# ─── SuperCollider ───────────────────────────────────────────────────────────

install_sc() {
    local src="$SCRIPT_DIR/sc"
    if [[ ! -f "$src/MRT2.scx" ]]; then
        err "SC source files not found in $src"
        return 1
    fi

    # Detect SuperCollider installation
    local sc_found=false

    if [[ -d "/Applications/SuperCollider.app" ]]; then
        sc_found=true
    elif mdfind "kMDItemCFBundleIdentifier == 'net.sourceforge.supercollider'" 2>/dev/null | grep -q "."; then
        sc_found=true
    elif [[ -d "$HOME/Library/Application Support/SuperCollider" ]]; then
        sc_found=true
    fi

    if ! $sc_found; then
        warn "No SuperCollider installation detected"
        return 0
    fi

    # Standard user extensions path
    local target="$HOME/Library/Application Support/SuperCollider/Extensions/MRT2"
    info "Installing SC extension → ${BOLD}$target${RESET}"
    mkdir -p "$target"

    cp "$src/MRT2.scx"      "$target/"
    cp "$src/mlx.metallib"   "$target/"
    cp "$src/MRT2.sc"        "$target/"
    cp "$src/example.scd"    "$target/"

    ok "SC: installed to $target"
    info "  Recompile the SC class library (Cmd-Shift-L) after installing."
}

# ─── Main ────────────────────────────────────────────────────────────────────

echo ""
echo -e "${BOLD}MRT2 Live-Coding Externals Installer${RESET}"
echo -e "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""

# Parse arguments — if none given, install all
targets=("${@:-max pd sc}")
if [[ $# -eq 0 ]]; then
    targets=(max pd sc)
fi

for t in "${targets[@]}"; do
    case "$t" in
        max) install_max ;;
        pd)  install_pd  ;;
        sc)  install_sc  ;;
        *)   err "Unknown target: $t (use max, pd, or sc)"; exit 1 ;;
    esac
    echo ""
done

echo -e "${GREEN}${BOLD}Done!${RESET}"
