#!/bin/sh
# Install Linksy (https://linksy.diary.mg) on Linux: it shows what it found (your system and desktop),
# lets you choose the app (GTK, Qt or both) and how (packages or Flatpak), then installs
# it, asking for your password once. Read it before running it if you like; it only
# installs Linksy.
#
#   curl -fsSL https://linksy.diary.mg/install.sh | sh             # asks
#   curl -fsSL https://linksy.diary.mg/install.sh | sh -s -- -y    # no questions: what fits this computer
#
# LINKSY_UI=qt or LINKSY_UI=gtk picks the app ahead of time. LINKSY_DRY_RUN=1 asks the same
# questions, then only says what it would download and run.
set -eu
DRY=${LINKSY_DRY_RUN:-}

V="0.9.2"
BASE="https://linksy.diary.mg/download"

YES=0
for arg in "$@"; do
  case "$arg" in
    -y|--yes) YES=1 ;;
    -h|--help) sed -n '2,11p' "$0" 2>/dev/null || true; exit 0 ;;
  esac
done
# Questions need a terminal: piped from curl, stdin is the script itself
if [ "$YES" = 0 ] && ! { : </dev/tty; } 2>/dev/null; then YES=1; fi

if [ -t 1 ]; then B=$(printf '\033[1m'); D=$(printf '\033[2m'); G=$(printf '\033[32m'); R=$(printf '\033[31m'); N=$(printf '\033[0m'); else B= D= G= R= N=; fi
say() { printf '%s\n' "$*"; }
step() { printf '  %s▸%s %s\n' "$B" "$N" "$*"; }
done_() { printf '\n  %s✓ %s%s\n\n' "$G" "$*" "$N"; }
fail() { printf '\n  %s✗ %s%s\n\n' "$R" "$*" "$N" >&2; exit 1; }

# ask "question" default choice…: prints the number picked (the default without a terminal)
ask() {
  q=$1 def=$2
  if [ "$YES" = 1 ]; then echo "$def"; return; fi
  printf '  %s%s%s [%s]: ' "$B" "$q" "$N" "$def" >/dev/tty
  read -r a </dev/tty || a=
  echo "${a:-$def}"
}
confirm() {
  [ "$YES" = 1 ] && return 0
  printf '  %s%s%s [Y/n]: ' "$B" "$1" "$N" >/dev/tty
  read -r a </dev/tty || a=
  case "$a" in [nN]*) return 1 ;; *) return 0 ;; esac
}

# "a b": whether version a is at least b
at_least() { [ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]; }

# ---- what this computer is ----

[ "$(uname -s)" = Linux ] || fail "Linksy is for Linux computers (and Android phones)."
[ "$(uname -m)" = x86_64 ] || fail "Linksy's packages are for x86_64 computers for now."
[ -r /etc/os-release ] || fail "Can't tell which distribution this is (no /etc/os-release)."
. /etc/os-release
IDS=" ${ID:-} ${ID_LIKE:-} "
SYSTEM="${PRETTY_NAME:-${NAME:-Linux}}"
DESKTOP="${XDG_CURRENT_DESKTOP:-none found}"

# Which packages fit here: rpm (Fedora), suse (openSUSE), deb (Debian, Ubuntu), none
FAMILY=none QT_OK=1 WHY=""
if [ -e /run/ostree-booted ]; then
  WHY="Fedora Atomic installs apps as Flatpaks."
else
  case "$IDS" in
    *" fedora "*) FAMILY=rpm ;;
    *" opensuse-tumbleweed "*|*" opensuse-slowroll "*) FAMILY=suse ;;
    *" debian "*|*" ubuntu "*)
      # New enough GTK and libadwaita: Debian 13, Ubuntu 24.04 and newer
      adw=$(apt-cache policy libadwaita-1-0 2>/dev/null | sed -n 's/^ *Candidate: *//p')
      if at_least "${adw:-0}" 1.5; then
        FAMILY=deb
        qt=$(apt-cache policy libqt6core6t64 2>/dev/null | sed -n 's/^ *Candidate: *//p')
        at_least "${qt:-0}" 6.8 || QT_OK=0
      else
        WHY="This release is older than Linksy's packages need (Debian 13, Ubuntu 24.04 or newer)."
      fi
      ;;
    *) WHY="There's no Linksy package for $SYSTEM yet." ;;
  esac
fi

installed=""
case "$FAMILY" in
  rpm|suse) installed=$(rpm -q --qf '%{VERSION}' linksy-common 2>/dev/null || true) ;;
  deb) installed=$(dpkg-query -W -f='${Version}' linksy-common 2>/dev/null || true) ;;
esac
case "$installed" in *"not installed"*) installed="" ;; esac

# ---- what it found ----

say ""
say "  ${B}Linksy $V installer${N}"
say ""
say "  ${D}System ${N}  $SYSTEM"
say "  ${D}Desktop${N}  $DESKTOP"
[ -n "$installed" ] && say "  ${D}Installed${N} Linksy $installed"
say ""

# ---- choices ----

# The app: Qt on KDE Plasma, GTK elsewhere, unless chosen
APP=1
case ":${XDG_CURRENT_DESKTOP:-}:" in *:KDE:*) [ "$QT_OK" = 1 ] && APP=2 ;; esac
case "${LINKSY_UI:-}" in qt) APP=2 ;; gtk) APP=1 ;; esac

HOW=1
if [ "$FAMILY" = none ]; then
  say "  $WHY"
  say "  The Flatpak works anyway: it brings everything it needs (the GTK app)."
  say ""
  confirm "Install the Linksy Flatpak?" || { say ""; exit 0; }
  HOW=2
else
  say "  Which app?"
  say "    1) GNOME and others ${D}(GTK)${N}"
  if [ "$QT_OK" = 1 ]; then
    say "    2) KDE Plasma ${D}(Qt 6)${N}"
    say "    3) Both ${D}(the menu opens the Qt one on Plasma)${N}"
  else
    say "    ${D}2) KDE Plasma: needs Plasma 6 with Qt 6.8 (Ubuntu 25.04, Debian 13 or newer)${N}"
  fi
  APP=$(ask "Choice" "$APP")
  case "$APP" in 1) ;; 2|3) [ "$QT_OK" = 1 ] || APP=1 ;; *) APP=1 ;; esac
  say ""
  say "  How?"
  say "    1) Packages ${D}(recommended: system-wide, every feature)${N}"
  say "    2) Flatpak ${D}(sandboxed, GTK app only; the webcam in every app and the USB cable need one more command)${N}"
  HOW=$(ask "Choice" 1)
  case "$HOW" in 2) ;; *) HOW=1 ;; esac
  say ""
fi

SUDO=sudo
[ "$(id -u)" = 0 ] && SUDO=
TMP=$(mktemp -d)
chmod 755 "$TMP"
trap 'rm -rf "$TMP"' EXIT
get() {
  step "Downloading $1"
  [ -n "$DRY" ] && return
  curl -fSL --retry 2 --progress-bar -o "$TMP/$1" "$BASE/$1" || fail "Couldn't download $1. Check your connection and try again."
}

# ---- Flatpak ----

if [ "$HOW" = 2 ]; then
  if ! command -v flatpak >/dev/null; then
    for pm in "apt install" "dnf install" "zypper install" "pacman -S"; do
      command -v "${pm%% *}" >/dev/null && fail "Flatpak isn't installed. Install it with: sudo $pm flatpak, then run this again."
    done
    fail "Flatpak isn't installed. Install it from your distribution, then run this again."
  fi
  [ "$FAMILY" = none ] || confirm "Install the Linksy Flatpak for your user?" || { say ""; exit 0; }
  get "linksy-$V.flatpak"
  step "Installing ${D}(Flatpak may download the GNOME runtime the first time)${N}"
  [ -n "$DRY" ] && { say "    flatpak install --user linksy-$V.flatpak"; exit 0; }
  flatpak install --user -y --noninteractive "$TMP/linksy-$V.flatpak" >/dev/null
  done_ "Linksy is installed. Open it from your apps."
  exit 0
fi

# ---- packages ----

case "$APP" in
  1) APPS="linksy" ;;
  2) APPS="linksy-qt" ;;
  3) APPS="linksy linksy-qt" ;;
esac
file() {
  case "$FAMILY" in
    rpm) echo "$1-$V-1.x86_64.rpm" ;;
    suse) echo "$1-$V-1.suse.x86_64.rpm" ;;
    deb) echo "${1}_${V}_amd64.deb" ;;
  esac
}
FILES="$(file linksy-common)"
for a in $APPS; do FILES="$FILES $(file "$a")"; done

say "  ${D}Packages${N} $(echo "$FILES" | sed 's/ /, /g')"
say ""
if [ "$installed" = "$V" ]; then
  confirm "Linksy $V is already installed. Add what's missing?" || { say ""; exit 0; }
elif [ -n "$installed" ]; then
  confirm "Update Linksy $installed to $V?" || { say ""; exit 0; }
else
  confirm "Install?" || { say ""; exit 0; }
fi
say ""

PATHS=""
for f in $FILES; do get "$f"; PATHS="$PATHS $TMP/$f"; done
step "Installing ${D}(your computer asks for your password)${N}"
if [ -n "$DRY" ]; then say "   $FAMILY:$PATHS" | sed "s|$TMP/||g"; exit 0; fi
# shellcheck disable=SC2086
case "$FAMILY" in
  rpm) $SUDO dnf install -y -q $PATHS ;;
  suse) $SUDO zypper --non-interactive --quiet install --allow-unsigned-rpm $PATHS ;;
  deb) $SUDO apt-get install -y -qq $PATHS ;;
esac || fail "The installation didn't finish (see above)."

done_ "Linksy $V is installed. Open it from your apps."
