#!/usr/bin/env bash
# One-line installer for the prebuilt mobux binary:
#
#   curl -fsSL https://raw.githubusercontent.com/mvhenten/mobux/main/install.sh | bash
#
# Downloads the latest GitHub release asset for the running architecture (Linux
# x86_64 and aarch64) built by scripts/build-release-asset.sh, verifies its
# sha256, and drops the binary in ~/.local/bin. The asset also carries the
# speech model, which lands in the data dir so dictation never fetches one.
# User-local only: no writes outside $HOME, no stdin.
#
# Overridable for tests and mirrors:
#   MOBUX_INSTALL_BASE_URL  where to fetch <asset> and <asset>.sha256 from
#                           (default: the GitHub "latest release" download URL;
#                           tests point this at a file:// directory)
#   MOBUX_INSTALL_DIR       install destination (default ~/.local/bin)
#   MOBUX_DATA_DIR          where the speech model lands
#                           (default ~/.local/share/mobux)

set -euo pipefail

CRATE="mobux"
BASE_URL="${MOBUX_INSTALL_BASE_URL:-https://github.com/mvhenten/mobux/releases/latest/download}"
INSTALL_DIR="${MOBUX_INSTALL_DIR:-$HOME/.local/bin}"
DATA_DIR="${MOBUX_DATA_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/mobux}"

say()  { printf '%s\n' "$*"; }
warn() { printf 'warning: %s\n' "$*" >&2; }
die()  { printf 'error: %s\n' "$*" >&2; exit 1; }

os="$(uname -s)"
arch="$(uname -m)"
case "${os}/${arch}" in
  Linux/x86_64)              TARGET="x86_64-unknown-linux-gnu" ;;
  Linux/aarch64|Linux/arm64) TARGET="aarch64-unknown-linux-gnu" ;;
  *) die "no prebuilt binary for ${os}/${arch} — mobux ships one for Linux x86_64 and Linux aarch64 only.
Build from source instead: cargo install ${CRATE}" ;;
esac
ASSET="${CRATE}-${TARGET}.tar.gz"

for tool in curl tar sha256sum; do
  command -v "$tool" >/dev/null 2>&1 || die "$tool is required but not installed"
done

CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}"
mkdir -p "$CACHE_DIR"
WORK="$(mktemp -d "${CACHE_DIR}/mobux-install.XXXXXX")"
trap 'rm -rf "$WORK"' EXIT

say "downloading ${BASE_URL}/${ASSET}"
curl -fsSL --retry 2 --max-time 3600 --speed-limit 1024 --speed-time 60 \
  -o "${WORK}/${ASSET}" "${BASE_URL}/${ASSET}" \
  || die "could not download ${ASSET} from ${BASE_URL}"
curl -fsSL --retry 2 --max-time 60 -o "${WORK}/${ASSET}.sha256" "${BASE_URL}/${ASSET}.sha256" \
  || die "could not download ${ASSET}.sha256 from ${BASE_URL}"

if ! (cd "$WORK" && sha256sum -c "${ASSET}.sha256" >/dev/null 2>&1); then
  die "sha256 verification failed for ${ASSET} — refusing to install"
fi
say "sha256 verified"

tar -xzf "${WORK}/${ASSET}" -C "$WORK" \
  || die "could not extract ${ASSET}"
[ -f "${WORK}/${CRATE}" ] || die "${ASSET} carries no ${CRATE} binary"

mkdir -p "$INSTALL_DIR"
# Stage inside the destination dir so the final move is an atomic rename and
# never leaves a half-written binary behind.
mv -f "${WORK}/${CRATE}" "${INSTALL_DIR}/.${CRATE}.new" \
  || die "could not write to ${INSTALL_DIR}"
chmod 755 "${INSTALL_DIR}/.${CRATE}.new"
mv -f "${INSTALL_DIR}/.${CRATE}.new" "${INSTALL_DIR}/${CRATE}"
say "installed ${INSTALL_DIR}/${CRATE}"

# The speech model rides in the same asset, already covered by the sha256 above.
# Put it where mobux looks so the first dictation transcribes instead of
# downloading. Assets from before the model shipped simply have no stt-models.
if [ -d "${WORK}/stt-models" ]; then
  mkdir -p "${DATA_DIR}/stt-models" \
    || die "could not create ${DATA_DIR}/stt-models for the speech model"
  cp -R "${WORK}/stt-models/." "${DATA_DIR}/stt-models/" \
    || die "could not write the speech model to ${DATA_DIR}/stt-models"
  say "installed the speech model in ${DATA_DIR}/stt-models"
fi

# A wrong-architecture asset, or one built against a newer glibc than this host
# has, downloads and verifies cleanly and then fails on every invocation. Prove
# the binary runs here rather than leaving a dead one behind without a word.
"${INSTALL_DIR}/${CRATE}" --version >/dev/null 2>&1 \
  || die "${INSTALL_DIR}/${CRATE} was installed but does not run on this host — the release binary does not match this architecture or this system's glibc.
Build from source instead: cargo install ${CRATE}"

case ":${PATH}:" in
  *":${INSTALL_DIR}:"*) ;;
  *) warn "${INSTALL_DIR} is not on your PATH — add it: export PATH=\"${INSTALL_DIR}:\$PATH\"" ;;
esac

command -v tmux >/dev/null 2>&1 || warn "tmux is not installed; mobux needs it at runtime"

host="$(hostname 2>/dev/null || echo your-host)"
cat <<EOF

Quick start:

  export MOBUX_AUTH_USER=me
  export MOBUX_PIN=12345
  ${CRATE} --port 5151
  ${CRATE} service install --port 5151   # or keep it running across reboots

Then open http://${host}:5151 from a phone on the same network.

mobux serves plain HTTP. Add --tls (or MOBUX_TLS=1) to serve HTTPS with a
generated certificate — recommended on any network you do not trust, and
unnecessary behind a TLS proxy.
EOF
