#!/bin/sh
# =============================================================================
#  Multilarm one-command installer
#
#      curl -fsSL https://multilarm.com/install.sh | sh
#
#  This does exactly what the three-line apt recipe in the documentation does,
#  and nothing else: it installs the signing key, adds the Multilarm apt
#  repository, and runs apt-get install. Every step is printed before it runs.
#
#  Three deliberate properties, because a piped-to-shell installer is asking a
#  stranger for a lot of trust:
#
#   * NO SILENT SUDO. If it needs root it says so and uses sudo visibly. If
#     sudo is not there it stops and prints the commands for you to run.
#   * NO CURL | SH INSIDE A CURL | SH. The key is downloaded to a file and
#     dearmoured; nothing fetched here is ever executed.
#   * IT REFUSES RATHER THAN IMPROVISES. An unsupported architecture, a
#     non-Debian system, a machine with no apt -- each one stops with the
#     reason and a link, instead of half-installing something. A half-installed
#     PA system is worse than none, because it looks installed.
#
#  Written for POSIX sh (dash on Debian), not bash. Validated in the build by
#  ops/test-install-script.mjs -- a generated or hand-edited installer that no
#  longer parses would otherwise be served, with a 200, to everybody.
# =============================================================================

set -eu

KEY_URL='https://multilarm.com/apt/multilarm.gpg'
REPO_LINE='deb [signed-by=/usr/share/keyrings/multilarm.gpg] https://multilarm.com/apt stable main'
KEYRING='/usr/share/keyrings/multilarm.gpg'
SOURCES='/etc/apt/sources.list.d/multilarm.list'

say()  { printf '%s\n' "$*"; }
step() { printf '\n==> %s\n' "$*"; }
die()  { printf '\nMultilarm installer: %s\n' "$*" >&2; exit 1; }

run() {
    printf '    $ %s\n' "$*"
    # shellcheck disable=SC2294
    eval "$SUDO $*"
}

say 'Multilarm installer'
say '-------------------'

# ---------------------------------------------------------------- the platform

[ "$(uname -s)" = 'Linux' ] || die "this installs the Linux package; on Windows use the installer at https://multilarm.com/downloads.html"

command -v apt-get >/dev/null 2>&1 || die "this needs apt (Debian, Raspberry Pi OS, Ubuntu). For anything else see https://multilarm.com/downloads.html"

# Only the architectures we actually build. Saying "amd64 is not built yet" is
# a far better answer than adding a repository that will never have a package
# in it and letting apt say "Unable to locate package multilarm".
ARCH="$(dpkg --print-architecture 2>/dev/null || echo unknown)"
case "$ARCH" in
    arm64|armhf) : ;;
    *) die "there is no Multilarm package for '$ARCH' yet -- the Linux builds are arm64 and armhf (Raspberry Pi). Windows: https://multilarm.com/downloads.html" ;;
esac
say "Architecture: $ARCH"

# ------------------------------------------------------------------- privilege

SUDO=''
if [ "$(id -u)" -ne 0 ]; then
    if command -v sudo >/dev/null 2>&1; then
        SUDO='sudo'
        say 'Root is needed to add a repository; sudo will be used and may ask for your password.'
    else
        say ''
        say 'This needs root and sudo is not installed. Run these three commands as root:'
        say ''
        say "  curl -fsSL $KEY_URL | gpg --dearmor -o $KEYRING"
        say "  echo '$REPO_LINE' > $SOURCES"
        say '  apt-get update && apt-get install -y multilarm'
        exit 1
    fi
fi

# ------------------------------------------------------------- what it will do

step 'This will:'
say "    1. install the Multilarm signing key at $KEYRING"
say "    2. add $SOURCES"
say '    3. apt-get update, then apt-get install multilarm'
say ''
say '    Nothing downloaded here is executed. Multilarm is installed as a'
say '    systemd --user service and stores its files under ~/.local/share.'

# ---------------------------------------------------------------- prerequisites

NEED=''
command -v curl  >/dev/null 2>&1 || NEED="$NEED curl"
command -v gpg   >/dev/null 2>&1 || NEED="$NEED gnupg"
[ -e /etc/ssl/certs/ca-certificates.crt ] || NEED="$NEED ca-certificates"
if [ -n "$NEED" ]; then
    step "Installing what the installer itself needs:$NEED"
    run "apt-get update"
    run "apt-get install -y$NEED"
fi

# ------------------------------------------------------------------------- key

step 'Installing the signing key'
TMPKEY="$(mktemp)"
trap 'rm -f "$TMPKEY"' EXIT INT TERM
curl -fsSL "$KEY_URL" -o "$TMPKEY" || die "could not download the signing key from $KEY_URL"
[ -s "$TMPKEY" ] || die 'the downloaded signing key was empty'
# --yes so a re-run over an existing keyring does not sit waiting for an answer
# nobody can give: this whole script is usually running with stdin on a pipe.
run "gpg --batch --yes --dearmor -o $KEYRING $TMPKEY"
run "chmod 0644 $KEYRING"

# ---------------------------------------------------------------------- source

step 'Adding the repository'
printf '%s\n' "$REPO_LINE" | $SUDO tee "$SOURCES" >/dev/null
say "    wrote $SOURCES"

# --------------------------------------------------------------------- install

step 'Installing Multilarm'
run "apt-get update"
run "apt-get install -y multilarm"

# ------------------------------------------------------------------ what next

PORT=6580
say ''
say 'Installed.'
say ''
say '  Start it:      systemctl --user start multilarm'
say '  On every boot: systemctl --user enable multilarm && sudo loginctl enable-linger "$USER"'
say "  Web Remote:    http://$(hostname -I 2>/dev/null | awk '{print $1}'):$PORT"
say '  Settings:      ~/.local/share/multilarm/Multilarm.config.xml'
say ''
say '  Set it up in a browser:  https://multilarm.com/multilarmconfiggenerator.html'
say '  First steps:             https://multilarm.com/docs.html'
say ''
say 'Personal, non-commercial use at home is free and nothing expires.'
