#!/bin/sh
set -eu

VTE_VERSION="0.70.6"
VTE_SHA256="e90e208dd5ab70f9675e6b532ebd5c8d830943be40eecbd9d36e980979080152"
VTE_URL="https://download.gnome.org/sources/vte/0.70/vte-${VTE_VERSION}.tar.xz"
MIN_RUST="1.85.0"
LIOS_CRATE_VERSION="${LIOS_CRATE_VERSION:-0.1.70}"
LIOS_BUILD_JOBS="${LIOS_BUILD_JOBS:-2}"
CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-2}"
export CARGO_BUILD_JOBS

say() {
    printf '%s\n' "lios: $*"
}

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

version_at_least() {
    oldest=$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n 1)
    [ "$oldest" = "$1" ]
}

check_dependencies() {
    command -v pkg-config >/dev/null 2>&1 || return 1
    pkg-config --atleast-version=4.0 gtk4 || return 1
    pkg-config --atleast-version=0.68 vte-2.91-gtk4 || return 1
}

check_rust() {
    command -v rustc >/dev/null 2>&1 || return 1
    rust_version=$(rustc --version | cut -d ' ' -f 2)
    version_at_least "$MIN_RUST" "$rust_version"
}

report() {
    say "architecture: $(uname -m)"
    if command -v pkg-config >/dev/null 2>&1; then
        gtk_version=$(pkg-config --modversion gtk4 2>/dev/null || printf 'missing')
        vte_version=$(pkg-config --modversion vte-2.91-gtk4 2>/dev/null || printf 'missing')
    else
        gtk_version="missing"
        vte_version="missing"
    fi
    if command -v rustc >/dev/null 2>&1; then
        rust_version=$(rustc --version | cut -d ' ' -f 2)
    else
        rust_version="missing"
    fi
    say "GTK4: ${gtk_version} (minimum 4.0)"
    say "VTE GTK4: ${vte_version} (minimum 0.68; upstream stable starts at 0.70)"
    say "Rust: ${rust_version} (minimum ${MIN_RUST})"
}

launch=false
case "${1:-}" in
    --check)
        report
        check_dependencies || exit 1
        check_rust || exit 1
        exit 0
        ;;
    --launch)
        launch=true
        shift
        ;;
    --help|-h)
        printf '%s\n' \
            "Usage: sh install-jetson.sh [--check]" \
            "" \
            "Installs Lios and its GTK4/VTE build dependencies with common Linux" \
            "package managers. Builds VTE GTK4 0.70.6 when the distribution lacks it."
        exit 0
        ;;
    "") ;;
    *) die "unknown option: $1" ;;
esac

install_dependencies() {
    if [ "$(id -u)" -eq 0 ]; then
        SUDO=""
    elif command -v sudo >/dev/null 2>&1; then
        SUDO="sudo"
    elif command -v doas >/dev/null 2>&1; then
        SUDO="doas"
    else
        die "sudo is required to install system dependencies"
    fi

    say "installing GTK4 and build prerequisites"
    if command -v apt-get >/dev/null 2>&1; then
        PACKAGE_FAMILY="apt"
        $SUDO apt-get update
        $SUDO apt-get install -y \
            build-essential ca-certificates curl gettext libglib2.0-dev libgtk-4-dev \
            libpango1.0-dev libpcre2-dev meson ninja-build pkg-config xz-utils zlib1g-dev
        if apt-cache show libvte-2.91-gtk4-dev >/dev/null 2>&1; then
            $SUDO apt-get install -y libvte-2.91-gtk4-dev
        fi
    elif command -v dnf >/dev/null 2>&1; then
        PACKAGE_FAMILY="dnf"
        $SUDO dnf install -y \
            gcc gcc-c++ make ca-certificates curl gettext glib2-devel gtk4-devel \
            pango-devel pcre2-devel meson ninja-build pkgconf-pkg-config xz zlib-devel
        if dnf -q info vte291-gtk4-devel >/dev/null 2>&1; then
            $SUDO dnf install -y vte291-gtk4-devel
        fi
    elif command -v pacman >/dev/null 2>&1; then
        PACKAGE_FAMILY="pacman"
        $SUDO pacman -S --needed --noconfirm \
            base-devel ca-certificates curl gettext glib2 gtk4 meson ninja pango pcre2 pkgconf vte4 xz zlib
    elif command -v zypper >/dev/null 2>&1; then
        PACKAGE_FAMILY="zypper"
        $SUDO zypper --non-interactive install \
            gcc gcc-c++ make ca-certificates curl gettext-tools glib2-devel gtk4-devel \
            pango-devel pcre2-devel meson ninja pkg-config xz zlib-devel
        if ! $SUDO zypper --non-interactive install vte-2_91-gtk4-devel; then
            $SUDO zypper --non-interactive install vte-devel || true
        fi
    elif command -v apk >/dev/null 2>&1; then
        PACKAGE_FAMILY="apk"
        $SUDO apk add --no-cache \
            build-base ca-certificates curl gettext glib-dev gtk4.0-dev meson ninja \
            pango-dev pcre2-dev pkgconf vte3-dev xz zlib-dev
    elif command -v xbps-install >/dev/null 2>&1; then
        PACKAGE_FAMILY="xbps"
        $SUDO xbps-install -Sy \
            base-devel ca-certificates curl gettext glib-devel gtk4-devel meson ninja \
            pango-devel pcre2-devel pkg-config vte3-devel xz zlib-devel
    else
        die "supported package manager not found (apt, dnf, pacman, zypper, apk, or xbps required)"
    fi

    if pkg-config --atleast-version=0.68 vte-2.91-gtk4 2>/dev/null; then
        say "using installed VTE GTK4 $(pkg-config --modversion vte-2.91-gtk4)"
        return
    fi

    say "distribution has no VTE GTK4 package; building upstream ${VTE_VERSION}"
    workdir=$(mktemp -d)
    trap 'rm -rf "$workdir"' EXIT HUP INT TERM
    archive="$workdir/vte-${VTE_VERSION}.tar.xz"
    curl -fL "$VTE_URL" -o "$archive"
    printf '%s  %s\n' "$VTE_SHA256" "$archive" | sha256sum -c -
    tar -C "$workdir" -xf "$archive"

    case "$PACKAGE_FAMILY" in
        apt) libdir="lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)" ;;
        dnf|zypper) libdir="lib64" ;;
        *) libdir="lib" ;;
    esac
    meson setup "$workdir/build" "$workdir/vte-${VTE_VERSION}" \
        --prefix=/usr/local \
        --libdir="$libdir" \
        -Dgtk3=false \
        -Dgtk4=true \
        -Ddocs=false \
        -Dfribidi=false \
        -Dgir=false \
        -Dglade=false \
        -Dgnutls=false \
        -Dicu=false \
        -Dvapi=false \
        -D_systemd=false
    ninja -C "$workdir/build" -j "$LIOS_BUILD_JOBS"
    $SUDO meson install -C "$workdir/build"
    if command -v ldconfig >/dev/null 2>&1; then
        $SUDO ldconfig
    fi
}

if check_dependencies; then
    say "using installed GTK4 $(pkg-config --modversion gtk4) and VTE GTK4 $(pkg-config --modversion vte-2.91-gtk4)"
else
    install_dependencies
    check_dependencies || {
        report
        die "GTK4 or VTE GTK4 did not meet the required version after installation"
    }
fi

rust_version=$(rustc --version 2>/dev/null | cut -d ' ' -f 2 || true)
if [ -z "$rust_version" ] || ! version_at_least "$MIN_RUST" "$rust_version"; then
    say "installing a current Rust toolchain with rustup"
    if command -v rustup >/dev/null 2>&1; then
        rustup toolchain install stable --profile minimal
        rustup default stable
    else
        curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
    fi
fi

if [ -f "$HOME/.cargo/env" ]; then
    # shellcheck disable=SC1091
    . "$HOME/.cargo/env"
fi
command -v cargo >/dev/null 2>&1 || die "cargo is unavailable after Rust installation"

report
say "installing Lios"
if [ -n "${LIOS_INSTALL_ROOT:-}" ]; then
    cargo install --locked --force --version "=${LIOS_CRATE_VERSION}" --features native --root "$LIOS_INSTALL_ROOT" lios
    lios_bin="$LIOS_INSTALL_ROOT/bin/lios"
else
    cargo install --locked --force --version "=${LIOS_CRATE_VERSION}" --features native lios
    lios_bin="${CARGO_HOME:-$HOME/.cargo}/bin/lios"
fi

[ -x "$lios_bin" ] || lios_bin=$(command -v lios || true)
[ -n "$lios_bin" ] || die "Lios installed but its binary was not found"
installed_version=$("$lios_bin" --version 2>/dev/null || true)
[ "$installed_version" = "lios ${LIOS_CRATE_VERSION}" ] || \
    die "installed binary failed native version verification (expected lios ${LIOS_CRATE_VERSION})"
"$lios_bin" --install

say "installation complete; launch Lios from the app menu or run $lios_bin"
if [ "$launch" = true ]; then
    exec "$lios_bin" "$@"
fi
