#!/bin/sh
# TeleCode installer (served at https://dl.telecode.cc/install.sh). One-liner:
#     curl -fsSL https://dl.telecode.cc/install.sh | sh
#
# Two install modes, picked automatically:
#
#   SYSTEM (needs root/sudo) -- when apt + root/sudo are available, or TELECODE_MODE=system.
#     Adds the signed TeleCode APT repository and installs a package; updates come via `apt upgrade`.
#       desktop edition (telecode)        -- GUI tray host + client, sign-in popup, graphical autostart.
#       server  edition (telecode-server) -- headless host as system-wide systemd services.
#     Override the edition with TELECODE_EDITION=desktop|server.
#     Updates are MANUAL (`sudo apt upgrade` when you choose); TeleCode never auto-upgrades itself.
#
#   USER (no sudo, no root) -- when sudo/root or apt are unavailable, or TELECODE_USERLOCAL=1.
#     Installs the headless host into ~/.local/share/telecode and runs it as a *user* systemd service
#     (systemctl --user), with `loginctl enable-linger` for start-at-boot. Nothing touches the system;
#     updates come from the app's own silent self-update. Works on any distro (no apt needed).
#     Set TELECODE_HOST_TAR=/path/to/telecode-host-linux-<arch>.tar.gz to install offline (no download).
#
# (Not to be confused with deploy/install.sh, which installs the relayd VPS service.)
set -e

BASE_URL="https://dl.telecode.cc"
REPO_URL="$BASE_URL/apt"
KEYRING="/etc/apt/keyrings/telecode.gpg"
LIST="/etc/apt/sources.list.d/telecode.list"
CONTROLD="https://api.telecode.cc"

say() { printf '\033[1;36m>>\033[0m %s\n' "$1"; }
err() { printf '\033[1;31m!!\033[0m %s\n' "$1" >&2; }

# --- a downloader (both modes need it) ---
if command -v curl >/dev/null 2>&1; then
  DL="curl -fsSL"
elif command -v wget >/dev/null 2>&1; then
  DL="wget -qO-"
else
  err "Need curl or wget."
  exit 1
fi

# arch for the user-mode tarball (uname works without dpkg, so the user path runs on any distro)
case "$(uname -m)" in
  x86_64 | amd64) UARCH="amd64" ;;
  aarch64 | arm64) UARCH="arm64" ;;
  *) UARCH="amd64" ;;
esac

# --- decide the mode ---
have_root_or_sudo() {
  [ "$(id -u)" -eq 0 ] && return 0
  command -v sudo >/dev/null 2>&1 && return 0
  return 1
}
MODE="${TELECODE_MODE:-auto}"
[ "${TELECODE_USERLOCAL:-0}" = "1" ] && MODE="user"
if [ "$MODE" = "auto" ]; then
  if command -v apt-get >/dev/null 2>&1 && have_root_or_sudo; then
    MODE="system"
  else
    MODE="user"
  fi
fi

# ============================================================================
# SYSTEM mode: signed APT repository + package install
# ============================================================================
system_install() {
  SUDO=""
  if [ "$(id -u)" -ne 0 ]; then
    if command -v sudo >/dev/null 2>&1; then
      SUDO="sudo"
    else
      err "System install needs root; re-run with sudo, or set TELECODE_USERLOCAL=1 for a no-sudo install."
      exit 1
    fi
  fi
  if ! command -v apt-get >/dev/null 2>&1; then
    err "System install currently supports Debian/Ubuntu (apt)."
    err "On other distros use the no-sudo user install:  TELECODE_USERLOCAL=1 $DL $BASE_URL/install.sh | sh"
    exit 1
  fi

  EDITION="${TELECODE_EDITION:-auto}"
  if [ "$EDITION" = "auto" ]; then
    if command -v systemctl >/dev/null 2>&1 && [ "$(systemctl get-default 2>/dev/null)" = "graphical.target" ]; then
      EDITION="desktop"
    else
      EDITION="server"
    fi
  fi
  case "$EDITION" in
    desktop) PKG="telecode" ;;
    server) PKG="telecode-server" ;;
    *) err "TELECODE_EDITION must be 'desktop' or 'server'."; exit 1 ;;
  esac
  # single stable channel (the beta channel was retired 2026-07-22 — all updates are manual anyway).
  CHANNEL="stable"
  say "TeleCode - system install, $EDITION edition ($PKG)."

  say "Adding the TeleCode APT repository ..."
  $SUDO install -m 0755 -d /etc/apt/keyrings
  $DL "$REPO_URL/key.gpg" | $SUDO tee "$KEYRING" >/dev/null
  $SUDO chmod a+r "$KEYRING"
  echo "deb [arch=$(dpkg --print-architecture) signed-by=$KEYRING] $REPO_URL $CHANNEL main" | $SUDO tee "$LIST" >/dev/null

  say "Updating package lists + installing $PKG ..."
  $SUDO apt-get update
  $SUDO apt-get install -y "$PKG"

  say "Done - TeleCode ($EDITION) is installed."
  echo
  if [ "$EDITION" = "server" ]; then
    cat <<'EOF'
To bring this machine online as a host, give it your account credentials, then start it:
  sudo install -d -m 0700 /etc/telecode
  sudo sh -c 'umask 077; printf "TELECODE_EMAIL=you@example.com\nTELECODE_PASSWORD=your-password\n" > /etc/telecode/host.env'
  sudo systemctl start telecode-pty telecode-host
The first successful start saves a device key, so you can clear the password afterwards.
EOF
  else
    echo "Open 'TeleCode Host' from your application menu (it also autostarts on login) and sign in via the popup."
  fi
  echo "Updates: 'sudo apt upgrade'  (or enable unattended-upgrades for automatic updates)."
}

# ============================================================================
# USER mode: ~/.local install + systemd --user service (no sudo)
# ============================================================================
user_install() {
  PREFIX="$HOME/.local/share/telecode"
  UNITDIR="$HOME/.config/systemd/user"
  CFGDIR="$HOME/.config/telecode"
  mkdir -p "$PREFIX" "$UNITDIR" "$CFGDIR"

  say "TeleCode - user install (no sudo) into $PREFIX"
  if [ -n "${TELECODE_HOST_TAR:-}" ] && [ -f "$TELECODE_HOST_TAR" ]; then
    # offline / air-gapped: install from a local tarball instead of downloading
    say "Installing the host from $TELECODE_HOST_TAR ..."
    if ! tar xz -C "$PREFIX" <"$TELECODE_HOST_TAR"; then
      err "Failed to extract $TELECODE_HOST_TAR"
      exit 1
    fi
  else
    TAR="$BASE_URL/telecode-host-linux-$UARCH.tar.gz"
    say "Downloading the host ($TAR) ..."
    if ! $DL "$TAR" | tar xz -C "$PREFIX"; then
      err "Failed to download/extract $TAR"
      exit 1
    fi
  fi
  chmod +x "$PREFIX/tchostd" "$PREFIX/tcsession" 2>/dev/null || true
  [ -f "$CFGDIR/host.env" ] || : >"$CFGDIR/host.env"
  chmod 600 "$CFGDIR/host.env"

  # systemd --user units. %h is expanded to the user's home by systemd at runtime, so these are portable.
  cat >"$UNITDIR/telecode-session.service" <<'EOF'
[Unit]
Description=TeleCode PTY daemon (owns live shells; survives host restarts)
After=network-online.target
Wants=network-online.target

[Service]
EnvironmentFile=-%h/.config/telecode/host.env
WorkingDirectory=%h/.local/share/telecode
ExecStart=%h/.local/share/telecode/tcsession -addr 127.0.0.1:8079
Restart=always
RestartSec=3

[Install]
WantedBy=default.target
EOF
  cat >"$UNITDIR/telecode-host.service" <<EOF
[Unit]
Description=TeleCode host (connects this machine to your account)
After=network-online.target telecode-session.service
Wants=network-online.target

[Service]
EnvironmentFile=-%h/.config/telecode/host.env
WorkingDirectory=%h/.local/share/telecode
ExecStart=%h/.local/share/telecode/tchostd -controld $CONTROLD
Restart=always
RestartSec=3

[Install]
WantedBy=default.target
EOF

  # make sure we can reach the per-user systemd manager (helps in fresh SSH / headless shells)
  [ -z "$XDG_RUNTIME_DIR" ] && export XDG_RUNTIME_DIR="/run/user/$(id -u)"

  if command -v systemctl >/dev/null 2>&1 && systemctl --user daemon-reload 2>/dev/null; then
    systemctl --user enable --now telecode-session.service telecode-host.service
    say "Host enabled as a user service (systemctl --user)."
    if loginctl enable-linger "$(id -un)" >/dev/null 2>&1; then
      say "Linger on: the host starts at boot, even before you log in."
    else
      echo "   To start at boot WITHOUT logging in, run once:  sudo loginctl enable-linger $(id -un)"
    fi
  else
    AUTO="$HOME/.config/autostart"
    mkdir -p "$AUTO"
    cat >"$AUTO/telecode-host.desktop" <<EOF
[Desktop Entry]
Type=Application
Name=TeleCode Host
Exec=$PREFIX/tchostd -controld $CONTROLD
X-GNOME-Autostart-enabled=true
EOF
    say "No user systemd here; the host will start when you log in (autostart entry written)."
  fi

  echo
  say "Done - TeleCode host installed for $(id -un), no sudo used."
  cat <<EOF
This host is headless (no tray / no login popup), so hand it your account credentials once:
  printf 'TELECODE_EMAIL=you@example.com\nTELECODE_PASSWORD=your-password\n' > ~/.config/telecode/host.env
  systemctl --user restart telecode-host          # (or log out / back in if it used autostart)
The first sign-in saves a device key, so you can blank the password afterwards.
Manage it:  systemctl --user status telecode-host   |   logs: journalctl --user -u telecode-host -f
EOF
}

if [ "$MODE" = "system" ]; then
  system_install
else
  user_install
fi
