#!/bin/sh
# The Textsmith installer.
#
#   curl -fsSL https://thetextsmith.com/install.sh | sh
#
# On Debian, Ubuntu and Linux Mint it adds The Textsmith's apt repository and
# installs the textsmith package; on Arch, the pacman repository. Both are
# signed with The Textsmith release key,
#   EACA 85A8 8536 7887 6820  15F8 9364 9288 FCB4 8B9E
# so later versions come with your usual system updates.
# Elsewhere it downloads the release, checks its checksum (and its signature,
# when gpg is installed) and puts textsmith in ~/.local/bin.
#
# TEXTSMITH_METHOD=local installs to ~/.local/bin on any distribution,
# without a repository and without sudo.

set -eu

BASE=${TEXTSMITH_BASE:-https://thetextsmith.com}
FINGERPRINT=${TEXTSMITH_FINGERPRINT:-EACA85A885367887682015F893649288FCB48B9E}
METHOD=${TEXTSMITH_METHOD:-auto}
TMP=""

say() { printf '%s\n' "$*"; }
die() { printf 'The Textsmith installer: %s\n' "$*" >&2; exit 1; }
cleanup() { [ -n "$TMP" ] && rm -rf "$TMP"; }

fetch() { # URL FILE
  if command -v curl >/dev/null 2>&1; then curl -fsSL "$1" -o "$2"
  elif command -v wget >/dev/null 2>&1; then wget -q "$1" -O "$2"
  else die "neither curl nor wget is installed."
  fi
}

as_root() {
  if [ "$(id -u)" -eq 0 ]; then "$@"
  elif command -v sudo >/dev/null 2>&1; then sudo "$@"
  else die "this step needs root, and sudo is not installed: run the installer as root."
  fi
}

# The release key, checked against the fingerprint above when gpg is here.
get_key() {
  fetch "$BASE/textsmith.asc" "$TMP/textsmith.asc"
  if command -v gpg >/dev/null 2>&1; then
    got=$(gpg --show-keys --with-colons "$TMP/textsmith.asc" 2>/dev/null | awk -F: '/^fpr/ { print $10; exit }')
    [ "$got" = "$FINGERPRINT" ] || die "the downloaded key is $got, not The Textsmith release key $FINGERPRINT. Nothing was installed."
    say "Release key checked: $FINGERPRINT"
  fi
}

install_apt() {
  arch=$(dpkg --print-architecture)
  [ "$arch" = amd64 ] || die "the package is for 64-bit PCs (amd64), and this is $arch. See $BASE/docs/installing/ to build from the source."
  get_key
  say "Adding The Textsmith's apt repository (sudo may ask for your password)..."
  as_root install -d -m 0755 /etc/apt/keyrings
  as_root install -m 0644 "$TMP/textsmith.asc" /etc/apt/keyrings/thetextsmith.asc
  printf 'deb [signed-by=/etc/apt/keyrings/thetextsmith.asc] %s/apt stable main\n' "$BASE" > "$TMP/thetextsmith.list"
  as_root install -m 0644 "$TMP/thetextsmith.list" /etc/apt/sources.list.d/thetextsmith.list
  as_root apt-get update
  as_root apt-get install -y textsmith
  done_message "Later versions arrive with your usual updates (sudo apt update && sudo apt upgrade)."
}

install_pacman() {
  get_key
  say "Adding The Textsmith's pacman repository (sudo may ask for your password)..."
  as_root pacman-key --add "$TMP/textsmith.asc"
  as_root pacman-key --lsign-key "$FINGERPRINT"
  if ! grep -q '^\[thetextsmith\]' /etc/pacman.conf; then
    printf '\n[thetextsmith]\nServer = %s/arch/$arch\n' "$BASE" > "$TMP/pacman.conf"
    as_root sh -c "cat '$TMP/pacman.conf' >> /etc/pacman.conf"
  fi
  # pacman asks before upgrading; its questions need the keyboard, not this script.
  if [ -r /dev/tty ]; then as_root pacman -Syu --needed textsmith < /dev/tty
  else as_root pacman -Syu --needed --noconfirm textsmith
  fi
  done_message "Later versions arrive with your usual updates (sudo pacman -Syu)."
}

install_local() {
  [ "$(uname -m)" = x86_64 ] || die "the prebuilt textsmith is for 64-bit PCs (x86_64), and this is $(uname -m). See $BASE/docs/installing/ to build from the source."
  if command -v ldconfig >/dev/null 2>&1 && ! ldconfig -p 2>/dev/null | grep -q 'libvte-2.91.so.0'; then
    say "The Textsmith needs VTE for GTK 3, which is not installed. Install it, then run this again:"
    say "  Fedora:    sudo dnf install vte291 gtk3"
    say "  openSUSE:  sudo zypper install libvte-2_91-0 gtk3"
    say "  Debian:    sudo apt install libvte-2.91-0 libgtk-3-0"
    exit 1
  fi
  glibc=$(getconf GNU_LIBC_VERSION 2>/dev/null | awk '{ print $2 }')
  case "$glibc" in
    2.[0-9]|2.[0-2][0-9]|2.3[0-8]) die "the prebuilt textsmith needs glibc 2.39 or later, and this system has $glibc. See $BASE/docs/installing/ to build from the source." ;;
  esac
  fetch "$BASE/download/latest" "$TMP/latest"
  version=$(tr -d ' \n\r' < "$TMP/latest")
  tarball="textsmith-$version.tar.gz"
  say "Downloading The Textsmith $version..."
  fetch "$BASE/download/$tarball" "$TMP/$tarball"
  fetch "$BASE/download/SHA256SUMS" "$TMP/SHA256SUMS"
  if command -v gpg >/dev/null 2>&1; then
    get_key
    fetch "$BASE/download/SHA256SUMS.asc" "$TMP/SHA256SUMS.asc"
    mkdir -m 700 "$TMP/gnupg"
    GNUPGHOME="$TMP/gnupg" gpg --quiet --import "$TMP/textsmith.asc" 2>/dev/null
    GNUPGHOME="$TMP/gnupg" gpg --quiet --verify "$TMP/SHA256SUMS.asc" "$TMP/SHA256SUMS" 2>/dev/null \
      || die "the signature on SHA256SUMS is not good. Nothing was installed."
    say "Signature checked."
  else
    say "gpg is not installed, so only the checksum is checked."
  fi
  (cd "$TMP" && grep " $tarball\$" SHA256SUMS | sha256sum -c --status) \
    || die "$tarball does not match its checksum. Nothing was installed."
  say "Checksum checked."
  tar -xzf "$TMP/$tarball" -C "$TMP"
  src="$TMP/textsmith-$version"
  bin="$HOME/.local/bin"
  apps="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
  mkdir -p "$bin" "$apps"
  if [ -L "$bin/textsmith" ]; then rm -f "$bin/textsmith"; fi   # an old link to the Electron edition
  install -m 755 "$src/bin/textsmith" "$bin/textsmith"
  sed "s|^Exec=textsmith|Exec=$bin/textsmith|" "$src/data/textsmith.desktop" > "$apps/textsmith.desktop"
  command -v update-desktop-database >/dev/null 2>&1 && update-desktop-database "$apps" >/dev/null 2>&1 || true
  done_message "To update later, run this installer again."
  case ":$PATH:" in *":$bin:"*) ;; *) say "Note: $bin is not on your PATH yet. Add it in ~/.bashrc or ~/.zshrc to type textsmith." ;; esac
}

done_message() {
  say ""
  say "Installed: $(textsmith --version 2>/dev/null || "$HOME/.local/bin/textsmith" --version)"
  say "Start it from your application menu, or type textsmith. F1 opens the manual."
  say "$1"
}

main() {
  TMP=$(mktemp -d)
  trap cleanup EXIT INT TERM
  say "The Textsmith installer"
  case "$METHOD" in
    apt) install_apt ;;
    pacman) install_pacman ;;
    local) install_local ;;
    auto)
      if command -v apt-get >/dev/null 2>&1 && command -v dpkg >/dev/null 2>&1; then install_apt
      elif command -v pacman >/dev/null 2>&1; then install_pacman
      else install_local
      fi ;;
    *) die "TEXTSMITH_METHOD is $METHOD; it can be apt, pacman, local or auto." ;;
  esac
}

# Everything above only defines; nothing runs until the whole script has arrived.
main "$@"
