#!/bin/sh
# PhoneRC web installer — generated from phone-rc/shortcut-launcher.
# Do not edit here; edit the source in the phone-rc repository.
set -eu

BASE_URL="https://stoicsoft.net/phonerc/downloads"
INSTALL_DIR="${PHONERC_COMPANION_HOME:-$HOME/.local/share/phonerc-companion}"

case "$(uname -s)" in
  Darwin) PLATFORM="macos" ;;
  Linux) PLATFORM="linux" ;;
  *) echo "This installer supports macOS and Linux." >&2; exit 1 ;;
esac
if [ "$PLATFORM" = "macos" ] && [ "$(uname -m)" != "arm64" ]; then
  echo "The current macOS Companion helper supports Apple silicon Macs only." >&2
  exit 1
fi

PYTHON="$(command -v python3 || true)"
if [ -z "$PYTHON" ] || ! "$PYTHON" -c 'import sys; raise SystemExit(sys.version_info < (3, 8))'; then
  echo "Python 3.8 or newer is required. Install Python, then try again." >&2
  exit 1
fi

# On many Linux distributions (Debian/Ubuntu in particular) the venv/ensurepip
# module ships in a separate package, so `python3 -m venv` fails later with a
# cryptic ensurepip error. Detect this now and give an actionable message
# instead of failing after the download.
if ! "$PYTHON" -c 'import ensurepip, venv' >/dev/null 2>&1; then
  PYVER="$("$PYTHON" -c 'import sys; print("%d.%d" % sys.version_info[:2])')"
  echo "Python's venv module is unavailable (ensurepip is missing)." >&2
  if command -v apt >/dev/null 2>&1 || command -v apt-get >/dev/null 2>&1; then
    echo "On Debian/Ubuntu, install it with:" >&2
    echo "    sudo apt install python3-venv python3.${PYVER#*.}-venv" >&2
  elif command -v dnf >/dev/null 2>&1; then
    echo "On Fedora/RHEL, install it with:" >&2
    echo "    sudo dnf install python3-pip" >&2
  else
    echo "Install the package that provides the Python venv and pip modules for your distribution, then try again." >&2
  fi
  echo "After installing it, re-run this installer." >&2
  exit 1
fi
for tool in curl unzip; do
  command -v "$tool" >/dev/null 2>&1 || { echo "$tool is required." >&2; exit 1; }
done

TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT HUP INT TERM
echo "Downloading PhoneRC Companion for $PLATFORM..."
curl --fail --location --proto '=https' --tlsv1.2 \
  "$BASE_URL/phonerc-companion-$PLATFORM.zip" --output "$TMP_DIR/companion.zip"
unzip -q "$TMP_DIR/companion.zip" -d "$TMP_DIR/outer"
INNER_ZIP="$(find "$TMP_DIR/outer" -type f -name '*.zip' -print -quit)"
if [ -n "$INNER_ZIP" ]; then
  unzip -q "$INNER_ZIP" -d "$TMP_DIR/package"
  SOURCE_DIR="$TMP_DIR/package/shortcut-launcher"
else
  SOURCE_DIR="$TMP_DIR/outer/shortcut-launcher"
fi
[ -f "$SOURCE_DIR/shortcut_launcher.py" ] || { echo "Invalid download." >&2; exit 1; }

mkdir -p "$INSTALL_DIR"
if [ -f "$INSTALL_DIR/config.json" ]; then
  cp "$INSTALL_DIR/config.json" "$TMP_DIR/config.json"
fi
cp -R "$SOURCE_DIR/." "$INSTALL_DIR/"
if [ -f "$TMP_DIR/config.json" ]; then
  cp "$TMP_DIR/config.json" "$INSTALL_DIR/config.json"
fi
if [ "$PLATFORM" = "macos" ]; then
  PACKAGED_HELPER="$INSTALL_DIR/macos-helper/PhoneRCCompanionHelper"
  RUNTIME_HELPER="$INSTALL_DIR/macos-helper/.build/release/PhoneRCCompanionHelper"
  [ -f "$PACKAGED_HELPER" ] || { echo "The macOS helper is missing from the package." >&2; exit 1; }
  mkdir -p "$(dirname "$RUNTIME_HELPER")"
  cp "$PACKAGED_HELPER" "$RUNTIME_HELPER"
  chmod +x "$RUNTIME_HELPER"
  # Copying an ad-hoc-signed executable can cause macOS to reject the new
  # inode. Re-sign it locally before the launcher's capability probe runs.
  codesign --force --sign - --timestamp=none "$RUNTIME_HELPER"
fi
"$PYTHON" -m venv "$INSTALL_DIR/.venv"
VENV_PYTHON="$INSTALL_DIR/.venv/bin/python"
# On Linux the companion talks to bluetoothd over D-Bus (dbus-fast ships
# wheels), so no C toolchain or BlueZ headers are needed.
"$VENV_PYTHON" -m pip install --disable-pip-version-check -r "$INSTALL_DIR/requirements.txt"
SELF_TEST_OUTPUT="$($VENV_PYTHON "$INSTALL_DIR/shortcut_launcher.py" --self-test)"
printf '%s\n' "$SELF_TEST_OUTPUT"
printf '%s\n' "$SELF_TEST_OUTPUT" | grep -q '^companion supported: yes$' || {
  echo "PhoneRC Companion prerequisites are incomplete; automatic startup was not configured." >&2
  exit 1
}
mkdir -p "$INSTALL_DIR/logs"

if [ "$PLATFORM" = "macos" ]; then
  AGENT_DIR="$HOME/Library/LaunchAgents"
  AGENT_FILE="$AGENT_DIR/net.stoicsoft.phonerc-companion.plist"
  mkdir -p "$AGENT_DIR"
  sed -e "s|__PYTHON__|$VENV_PYTHON|g" -e "s|__DIR__|$INSTALL_DIR|g" > "$AGENT_FILE" <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>Label</key><string>net.stoicsoft.phonerc-companion</string>
<key>ProgramArguments</key><array><string>__PYTHON__</string><string>-u</string><string>__DIR__/shortcut_launcher.py</string><string>--both</string><string>--verbose</string></array>
<key>WorkingDirectory</key><string>__DIR__</string>
<key>RunAtLoad</key><true/><key>KeepAlive</key><true/>
<key>StandardOutPath</key><string>__DIR__/logs/companion.log</string>
<key>StandardErrorPath</key><string>__DIR__/logs/companion-error.log</string>
</dict></plist>
EOF
  launchctl bootout "gui/$(id -u)" "$AGENT_FILE" >/dev/null 2>&1 || true
  launchctl bootstrap "gui/$(id -u)" "$AGENT_FILE"
  "$VENV_PYTHON" -c 'from ApplicationServices import AXIsProcessTrustedWithOptions, kAXTrustedCheckOptionPrompt; AXIsProcessTrustedWithOptions({kAXTrustedCheckOptionPrompt: True})' || true
  echo "Installed and started. Approve the macOS Accessibility request so PhoneRC can paste text and handle hotkeys."
else
  # Register the default shortcuts so they work right after installation, the
  # way the Windows and macOS installers already do. On GNOME this binds the
  # key combos through dconf; other desktops get .desktop entries and
  # ~/.local/bin scripts that the user binds in their own keyboard settings.
  NATIVE_SHORTCUTS="no"
  if "$VENV_PYTHON" "$INSTALL_DIR/shortcut_launcher.py" --install; then
    # Either CLI can bind the keys; only then does GNOME own the combos.
    if command -v dconf >/dev/null 2>&1 || command -v gsettings >/dev/null 2>&1; then
      NATIVE_SHORTCUTS="yes"
    fi
  else
    echo "Could not register native shortcuts; the background listener will handle them instead." >&2
  fi

  # GNOME now owns the key combos, so run the companion without the pynput
  # hotkey listener — otherwise every shortcut fires twice. Where the keys are
  # not bound for us, the listener stays on and provides them.
  if [ "$NATIVE_SHORTCUTS" = "yes" ]; then
    LAUNCH_MODE="--companion"
  else
    LAUNCH_MODE="--both"
  fi

  if command -v systemctl >/dev/null 2>&1; then
    SERVICE_DIR="$HOME/.config/systemd/user"
    mkdir -p "$SERVICE_DIR"
    sed -e "s|__PYTHON__|$VENV_PYTHON|g" -e "s|__DIR__|$INSTALL_DIR|g" \
      -e "s|__MODE__|$LAUNCH_MODE|g" > "$SERVICE_DIR/phonerc-companion.service" <<'EOF'
[Unit]
Description=PhoneRC Companion
# Keep retrying indefinitely: the Bluetooth stack is often not ready yet at
# login, and the default start limit would give up permanently after a few
# fast failures ("Start request repeated too quickly").
StartLimitIntervalSec=0
[Service]
Type=simple
WorkingDirectory=__DIR__
ExecStart=__PYTHON__ __DIR__/shortcut_launcher.py __MODE__
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
EOF
    systemctl --user daemon-reload
    systemctl --user enable --now phonerc-companion.service
    # Apply the new ExecStart when reinstalling over an already-running service.
    systemctl --user restart phonerc-companion.service

    # Surface a failed start here rather than leaving a dead service to be
    # discovered later. RestartSec delays the first retry, so a service that
    # exited immediately is still visible as inactive at this point.
    sleep 3
    if ! systemctl --user is-active --quiet phonerc-companion.service; then
      echo "" >&2
      echo "The PhoneRC Companion service did not stay running:" >&2
      systemctl --user --no-pager --lines=20 status phonerc-companion.service >&2 || true
      echo "" >&2
      echo "The shortcuts above are installed and work regardless; this affects" >&2
      echo "Unicode text input only. systemd will keep retrying every 10s." >&2
    fi
  else
    mkdir -p "$HOME/.config/autostart"
    cat > "$HOME/.config/autostart/phonerc-companion.desktop" <<EOF
[Desktop Entry]
Type=Application
Name=PhoneRC Companion
Exec=$VENV_PYTHON $INSTALL_DIR/shortcut_launcher.py $LAUNCH_MODE
Path=$INSTALL_DIR
Terminal=false
X-GNOME-Autostart-enabled=true
EOF
    "$VENV_PYTHON" "$INSTALL_DIR/shortcut_launcher.py" "$LAUNCH_MODE" >/dev/null 2>&1 &
  fi

  if [ "$NATIVE_SHORTCUTS" = "yes" ]; then
    echo "Installed and started. Default shortcuts are registered and active."
  else
    echo "Installed and started. Shortcuts are handled by the background listener."
    echo "Bind the scripts in ~/.local/bin to keys in your desktop's keyboard settings for native shortcuts."
  fi
  if ! command -v xdotool >/dev/null 2>&1; then
    echo "Note: xdotool is not installed, so Unicode text paste will not work."
    echo "      Install it with: sudo apt install xdotool"
  fi
  if [ "$NATIVE_SHORTCUTS" = "no" ] && [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then
    echo "Note: global hotkeys from the background listener do not work under Wayland."
    echo "      Bind the ~/.local/bin scripts in your desktop's keyboard settings instead."
  fi
fi
echo "Installed at: $INSTALL_DIR"
