#!/bin/bash
# install-modules.sh — install optional modules on an already-configured system

set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULES="$SCRIPT_DIR/modules"
APPS="$MODULES/optional-Modules/apps"
LOG="$HOME/dotfiles-modules.log"
TMP_D="$(mktemp -d)"
trap 'rm -rf "$TMP_D"' EXIT

BACKTITLE="the_miro's Arch Dotfiles — Module Installer"

export DIALOGRC="$TMP_D/dialogrc"
cat > "$DIALOGRC" <<'EOF'
use_shadow = ON
use_colors = ON
screen_color              = (BLACK,BLACK,ON)
shadow_color              = (BLACK,BLACK,ON)
title_color               = (MAGENTA,BLACK,ON)
border_color              = (MAGENTA,BLACK,ON)
button_active_color       = (BLACK,MAGENTA,ON)
button_inactive_color     = (WHITE,BLACK,OFF)
button_key_active_color   = (BLACK,CYAN,ON)
button_key_inactive_color = (CYAN,BLACK,ON)
button_label_active_color   = (BLACK,MAGENTA,ON)
button_label_inactive_color = (WHITE,BLACK,OFF)
inputbox_color        = (WHITE,BLACK,OFF)
inputbox_border_color = (MAGENTA,BLACK,ON)
menubox_color         = (WHITE,BLACK,OFF)
menubox_border_color  = (MAGENTA,BLACK,ON)
item_color            = (WHITE,BLACK,OFF)
item_selected_color   = (BLACK,MAGENTA,ON)
tag_color             = (CYAN,BLACK,ON)
tag_selected_color    = (BLACK,CYAN,ON)
tag_key_color         = (CYAN,BLACK,ON)
tag_key_selected_color = (BLACK,CYAN,ON)
check_color           = (WHITE,BLACK,OFF)
check_selected_color  = (BLACK,MAGENTA,ON)
uarrow_color          = (MAGENTA,BLACK,ON)
darrow_color          = (MAGENTA,BLACK,ON)
EOF

STEP=0
TOTAL=0

require_dialog() {
    command -v dialog &>/dev/null && return
    echo "dialog not found — installing..."
    sudo pacman -S --noconfirm dialog || { echo "Failed to install dialog."; exit 1; }
}

die() {
    clear
    printf "\n  Error: %s\n\n" "$1" >&2
    exit 1
}

log_sep() {
    printf "\n══════════════════════════════════\n  %s\n  %s\n" "$1" "$(date)" >> "$LOG"
}

run_module() {
    local label="$1" script="$2"
    STEP=$(( STEP + 1 ))
    log_sep "[$STEP/$TOTAL] $label"

    clear
    printf "\n\033[1;35m  [$STEP/$TOTAL] %s\033[0m\n" "$label"
    printf "\033[35m  ─────────────────────────────────────────────\033[0m\n\n"

    local rc=0
    bash "$script" 2>&1 | tee -a "$LOG" || rc=${PIPESTATUS[0]}

    if [[ $rc -ne 0 ]]; then
        dialog --backtitle "$BACKTITLE" \
               --title " Module Failed " \
               --yesno "$label exited with code $rc.\n\nContinue anyway?" 8 54 \
            || { clear; exit 1; }
    fi
}

count_steps() {
    local sel="$1"
    TOTAL=0
    [[ "$sel" == *"kde-plasma"*      ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"gnome"*           ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"cosmic"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"niri"*            ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"xfce"*            ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"lxqt"*            ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"ollama"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"llama-cpp"*       ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"open-webui"*      ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"claude"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"anti-malware"*     ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"networking-cli"*  ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"disk-recovery"*   ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"himalaya"*        ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"gnuplot"*         ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"povray"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"blender"*         ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"toot"*            ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"db-clients"*      ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"mysql"*           ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"productivity"*    ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"yt-dlp"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"sox"*             ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"imagemagick"*     ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"ffmpeg"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"localtunnel"*     ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"butter"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"plymouth"*         ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"plymouth-custom"* ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"greetd-regreet"*  ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"lightdm"*         ]] && TOTAL=$(( TOTAL + 1 ))
    # 'ly' is padded/quote-stripped so it doesn't substring-match 'p(ly)mouth'.
    [[ " ${sel//\"/} " == *" ly "*   ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"tlp"*             ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"steam"*           ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"vesktop"*         ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"spotify"*         ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"prism"*           ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"vintagestory"*    ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"openarena"*       ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"tetris"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"doom"*            ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"sauerbraten"*     ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"stuntrally"*      ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"localsend"*       ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"croc"*            ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"onlyoffice"*      ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"wireshark"*       ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"k8s"*             ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"docker"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"podman"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"cockpit"*         ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"ssh-server"*      ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"freeipa-client"*  ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"freeipa-server"*  ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"freeipa-image"*   ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"python"*          ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"zfs"*             ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"wprs"*            ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"chromium"*        ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"firefox-browser"* ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"zen-browser"*     ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"nyxt"*            ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"librewolf"*       ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"min-browser"*     ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"vscodium"*        ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"zed-ide"*         ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"geany"*           ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"codeblocks"*      ]] && TOTAL=$(( TOTAL + 1 ))
    [[ "$sel" == *"kate"*            ]] && TOTAL=$(( TOTAL + 1 ))
}

if [[ $EUID -eq 0 ]]; then
    # Root context (e.g. archiso chroot): shim sudo as a passthrough
    mkdir -p "$TMP_D/bin"
    printf '#!/bin/bash\nexec "$@"\n' > "$TMP_D/bin/sudo"
    chmod +x "$TMP_D/bin/sudo"
    export PATH="$TMP_D/bin:$PATH"
fi
command -v pacman &>/dev/null || die "pacman not found — Arch Linux required."

require_dialog

> "$LOG"
printf "Module install: %s\n" "$(date)" >> "$LOG"

dialog --backtitle "$BACKTITLE" \
    --title " Module Installer " \
    --msgbox "\n\
  Install optional modules on an existing system.\n\
  ─────────────────────────────────────────────────\n\
\n\
  Select any combination of modules below.\n\
  Each module is idempotent — safe to re-run.\n\
\n\
  Log: $LOG\n" 13 62

SELECTED=$(dialog --backtitle "$BACKTITLE" \
    --title " Select Modules " \
    --checklist "Space toggles  ·  Enter confirms  ·  Arrow keys scroll" 40 76 32 \
    \
    "kde-plasma"      "KDE Plasma        full Plasma DE + sddm"                  off \
    "gnome"           "GNOME             GNOME Shell + gdm"                      off \
    "cosmic"          "COSMIC            Rust-based Wayland DE (System76)"       off \
    "niri"            "Niri              scrollable-tiling Wayland compositor"   off \
    "xfce"            "XFCE              lightweight X11 DE + lightdm"           off \
    "lxqt"            "LXQt              lightweight Qt X11 DE + sddm"           off \
    \
    "ollama"          "Ollama            local LLM runner + API server"          off \
    "llama-cpp"       "llama.cpp         standalone inference CLI + server"      off \
    "open-webui"      "Open WebUI        browser UI for Ollama / LLM backends"  off \
    "claude"          "Claude Code       Anthropic CLI via npm"                 off \
    "anti-malware"    "Anti-Malware      clamav · clamtk · rkhunter · chkrootkit" off \
    "networking-cli"  "Networking CLI    nmap · nethogs · mitmproxy · httpie"  off \
    "disk-recovery"   "Disk Recovery     ddrescue · f3"                         off \
    "himalaya"        "Himalaya          terminal email client (AUR)"           off \
    "gnuplot"         "Gnuplot           scientific plotting"                   off \
    "povray"          "POV-Ray           ray-tracing renderer"                  off \
    "blender"         "Blender           3D creation suite"                     off \
    "toot"            "toot              Mastodon CLI client (AUR)"             off \
    "db-clients"      "DB Clients        pgcli · mycli"                         off \
    "mysql"           "MySQL / MariaDB   mariadb server + setup"                off \
    "productivity"    "Productivity      taskwarrior · watson · jrnl"           off \
    "yt-dlp"          "yt-dlp            YouTube / media downloader"            off \
    "sox"             "SoX               audio processing toolkit"              off \
    "imagemagick"     "ImageMagick       image manipulation"                    off \
    "ffmpeg"          "FFmpeg extras     thumbnailer · GStreamer codecs"        off \
    "localtunnel"     "LocalTunnel       expose localhost via tunnel"           off \
    "butter"          "butter            btrfs snapshot backup (AUR)"           off \
    "plymouth"        "Plymouth          boot splash — skull logo + boot-log tail"    off \
    "plymouth-custom" "Plymouth (custom) boot splash — supply your own image"  off \
    "greetd-regreet"  "greetd + ReGreet  Wayland greeter, cyberqueer-themed"   off \
    "lightdm"         "LightDM           GTK greeter, cyberqueer (Xorg)"       off \
    "ly"              "ly                TUI display manager, cyberqueer"       off \
    "tlp"             "TLP               laptop power management"               off \
    \
    "steam"           "Steam             gaming platform"                       off \
    "vesktop"         "Vesktop           Discord + Vencord theme"               off \
    "spotify"         "Spotify           launcher + Spicetify theming"          off \
    "prism"           "PrismLauncher     Minecraft launcher (Flatpak)"          off \
    "vintagestory"    "Vintage Story     survival game (AUR)"                   off \
    "openarena"       "OpenArena         open-source Quake III Arena"           off \
    "tetris"          "Tetris CLI        bastet · vitetris"                     off \
    "doom"            "Doom              Chocolate Doom + Freedoom data"        off \
    "sauerbraten"     "Sauerbraten       open-source FPS (Cube 2)"             off \
    "stuntrally"      "Stunt Rally       rally racing game (Flatpak)"          off \
    "localsend"       "LocalSend         LAN file transfer (AUR)"               off \
    "croc"            "croc              cross-platform file transfer"          off \
    "onlyoffice"      "OnlyOffice        office suite (AUR)"                   off \
    "wireshark"       "Wireshark         network packet analyser (GUI)"         off \
    "k8s"             "Kubernetes tools  kubectl · podman-desktop"              off \
    "docker"          "Docker            docker · docker-compose"               off \
    "podman"          "Podman            rootless containers · buildah"         off \
    "cockpit"         "Cockpit           web UI · machines · podman"            off \
    "ssh-server"      "SSH server        openssh · key-auth · enabled"          off \
    "freeipa-client"  "FreeIPA Client    sssd + ipa-client-install + enrollment"  off \
    "freeipa-server"  "FreeIPA Server    interactive server setup + client gen"  off \
    "freeipa-image"   "FreeIPA Image     OCI/LXC/Proxmox LXC builder + Keycloak" off \
    "python"          "Python tools      pyright · pipx · pynvim"              off \
    "zfs"             "ZFS               zfs-dkms kernel module"                off \
    "wprs"            "WPRS              wprs-git (AUR)"                        off \
    \
    "chromium"        "Chromium          open-source browser (official)"        off \
    "firefox-browser" "Firefox           Mozilla browser (official)"            off \
    "zen-browser"     "Zen Browser       Firefox-based privacy browser (AUR)"   off \
    "nyxt"            "Nyxt              keyboard-driven browser (AUR)"         off \
    "librewolf"       "LibreWolf         hardened Firefox fork (AUR)"           off \
    "min-browser"     "Min               minimal Electron browser (AUR)"        off \
    \
    "vscodium"        "VSCodium          telemetry-free VS Code (AUR)"          off \
    "zed-ide"         "Zed               high-performance Rust IDE (official)"  off \
    "geany"           "Geany             lightweight IDE + plugins (official)"  off \
    "codeblocks"      "Code::Blocks      C/C++ IDE (official)"                  off \
    "kate"            "Kate              KDE advanced text editor (official)"   off \
    3>&1 1>&2 2>&3) || { clear; echo "Aborted."; exit 0; }

[[ -z "$SELECTED" ]] && { clear; echo "Nothing selected."; exit 0; }

# ── Plymouth custom logo ───────────────────────────────────────────────────────
# Ask for image path now (before the confirmation dialog) so it can appear in
# the summary.  The path is exported and picked up by plymouth-custom.sh.
PLYMOUTH_LOGO_SRC=""
if [[ "$SELECTED" == *"plymouth-custom"* ]]; then
    PLYMOUTH_LOGO_SRC=$(dialog --backtitle "$BACKTITLE" \
        --title " Plymouth — Custom Logo " \
        --inputbox "\n  Path to the image to display during boot.\n\n  PNG  → used as-is (must already be the right size)\n  SVG  → converted to PNG automatically via rsvg-convert\n\n  Leave blank to use a transparent placeholder.\n" \
        13 66 "" \
        3>&1 1>&2 2>&3) || PLYMOUTH_LOGO_SRC=""

    if [[ -n "$PLYMOUTH_LOGO_SRC" && ! -f "$PLYMOUTH_LOGO_SRC" ]]; then
        dialog --backtitle "$BACKTITLE" \
            --title " Warning " \
            --msgbox "\n  File not found:\n  $PLYMOUTH_LOGO_SRC\n\n  A transparent placeholder will be used instead.\n" \
            9 62
        PLYMOUTH_LOGO_SRC=""
    fi
fi

SUMMARY=""
[[ "$SELECTED" == *"kde-plasma"*     ]] && SUMMARY+="  ✦ KDE Plasma\n"
[[ "$SELECTED" == *"gnome"*          ]] && SUMMARY+="  ✦ GNOME\n"
[[ "$SELECTED" == *"cosmic"*         ]] && SUMMARY+="  ✦ COSMIC\n"
[[ "$SELECTED" == *"niri"*           ]] && SUMMARY+="  ✦ Niri\n"
[[ "$SELECTED" == *"xfce"*           ]] && SUMMARY+="  ✦ XFCE\n"
[[ "$SELECTED" == *"lxqt"*           ]] && SUMMARY+="  ✦ LXQt\n"
[[ "$SELECTED" == *"ollama"*         ]] && SUMMARY+="  ✦ Ollama\n"
[[ "$SELECTED" == *"llama-cpp"*      ]] && SUMMARY+="  ✦ llama.cpp\n"
[[ "$SELECTED" == *"open-webui"*     ]] && SUMMARY+="  ✦ Open WebUI\n"
[[ "$SELECTED" == *"claude"*         ]] && SUMMARY+="  ✦ Claude Code\n"
[[ "$SELECTED" == *"anti-malware"*   ]] && SUMMARY+="  ✦ Anti-Malware (clamav, clamtk, rkhunter, chkrootkit)\n"
[[ "$SELECTED" == *"networking-cli"* ]] && SUMMARY+="  ✦ Networking CLI (nmap, nethogs, mitmproxy, httpie)\n"
[[ "$SELECTED" == *"disk-recovery"*  ]] && SUMMARY+="  ✦ Disk Recovery (ddrescue, f3)\n"
[[ "$SELECTED" == *"himalaya"*       ]] && SUMMARY+="  ✦ Himalaya\n"
[[ "$SELECTED" == *"gnuplot"*        ]] && SUMMARY+="  ✦ Gnuplot\n"
[[ "$SELECTED" == *"povray"*         ]] && SUMMARY+="  ✦ POV-Ray\n"
[[ "$SELECTED" == *"blender"*        ]] && SUMMARY+="  ✦ Blender\n"
[[ "$SELECTED" == *"toot"*           ]] && SUMMARY+="  ✦ toot\n"
[[ "$SELECTED" == *"db-clients"*     ]] && SUMMARY+="  ✦ DB Clients (pgcli, mycli)\n"
[[ "$SELECTED" == *"mysql"*          ]] && SUMMARY+="  ✦ MySQL / MariaDB\n"
[[ "$SELECTED" == *"productivity"*   ]] && SUMMARY+="  ✦ Productivity (taskwarrior, watson, jrnl)\n"
[[ "$SELECTED" == *"yt-dlp"*         ]] && SUMMARY+="  ✦ yt-dlp\n"
[[ "$SELECTED" == *"sox"*            ]] && SUMMARY+="  ✦ SoX\n"
[[ "$SELECTED" == *"imagemagick"*    ]] && SUMMARY+="  ✦ ImageMagick\n"
[[ "$SELECTED" == *"ffmpeg"*         ]] && SUMMARY+="  ✦ FFmpeg extras\n"
[[ "$SELECTED" == *"localtunnel"*    ]] && SUMMARY+="  ✦ LocalTunnel\n"
[[ "$SELECTED" == *"butter"*          ]] && SUMMARY+="  ✦ butter (btrfs backup)\n"
[[ "$SELECTED" == *"plymouth"*        ]] && SUMMARY+="  ✦ Plymouth boot splash\n"
[[ "$SELECTED" == *"greetd-regreet"*  ]] && SUMMARY+="  ✦ greetd + ReGreet greeter\n"
[[ "$SELECTED" == *"lightdm"*         ]] && SUMMARY+="  ✦ LightDM greeter\n"
[[ " ${SELECTED//\"/} " == *" ly "*   ]] && SUMMARY+="  ✦ ly greeter\n"
if [[ "$SELECTED" == *"plymouth-custom"* ]]; then
    if [[ -n "$PLYMOUTH_LOGO_SRC" ]]; then
        SUMMARY+="  ✦ Plymouth (custom logo: $PLYMOUTH_LOGO_SRC)\n"
    else
        SUMMARY+="  ✦ Plymouth (custom logo: placeholder — no file given)\n"
    fi
fi
[[ "$SELECTED" == *"tlp"*            ]] && SUMMARY+="  ✦ TLP\n"
[[ "$SELECTED" == *"steam"*          ]] && SUMMARY+="  ✦ Steam\n"
[[ "$SELECTED" == *"vesktop"*        ]] && SUMMARY+="  ✦ Vesktop\n"
[[ "$SELECTED" == *"spotify"*        ]] && SUMMARY+="  ✦ Spotify\n"
[[ "$SELECTED" == *"prism"*          ]] && SUMMARY+="  ✦ PrismLauncher\n"
[[ "$SELECTED" == *"vintagestory"*   ]] && SUMMARY+="  ✦ Vintage Story\n"
[[ "$SELECTED" == *"openarena"*      ]] && SUMMARY+="  ✦ OpenArena\n"
[[ "$SELECTED" == *"tetris"*         ]] && SUMMARY+="  ✦ Tetris CLI (bastet · vitetris)\n"
[[ "$SELECTED" == *"doom"*           ]] && SUMMARY+="  ✦ Doom\n"
[[ "$SELECTED" == *"sauerbraten"*    ]] && SUMMARY+="  ✦ Sauerbraten\n"
[[ "$SELECTED" == *"stuntrally"*     ]] && SUMMARY+="  ✦ Stunt Rally\n"
[[ "$SELECTED" == *"localsend"*      ]] && SUMMARY+="  ✦ LocalSend\n"
[[ "$SELECTED" == *"croc"*           ]] && SUMMARY+="  ✦ croc\n"
[[ "$SELECTED" == *"onlyoffice"*     ]] && SUMMARY+="  ✦ OnlyOffice\n"
[[ "$SELECTED" == *"wireshark"*      ]] && SUMMARY+="  ✦ Wireshark\n"
[[ "$SELECTED" == *"k8s"*            ]] && SUMMARY+="  ✦ Kubernetes tools\n"
[[ "$SELECTED" == *"docker"*         ]] && SUMMARY+="  ✦ Docker\n"
[[ "$SELECTED" == *"podman"*         ]] && SUMMARY+="  ✦ Podman\n"
[[ "$SELECTED" == *"cockpit"*        ]] && SUMMARY+="  ✦ Cockpit\n"
[[ "$SELECTED" == *"ssh-server"*     ]] && SUMMARY+="  ✦ SSH server\n"
[[ "$SELECTED" == *"freeipa-client"* ]] && SUMMARY+="  ✦ FreeIPA Client\n"
[[ "$SELECTED" == *"freeipa-server"* ]] && SUMMARY+="  ✦ FreeIPA Server\n"
[[ "$SELECTED" == *"freeipa-image"*  ]] && SUMMARY+="  ✦ FreeIPA Image Builder\n"
[[ "$SELECTED" == *"python"*         ]] && SUMMARY+="  ✦ Python tools\n"
[[ "$SELECTED" == *"zfs"*            ]] && SUMMARY+="  ✦ ZFS\n"
[[ "$SELECTED" == *"wprs"*           ]] && SUMMARY+="  ✦ WPRS\n"
[[ "$SELECTED" == *"chromium"*       ]] && SUMMARY+="  ✦ Chromium\n"
[[ "$SELECTED" == *"firefox-browser"* ]] && SUMMARY+="  ✦ Firefox\n"
[[ "$SELECTED" == *"zen-browser"*    ]] && SUMMARY+="  ✦ Zen Browser\n"
[[ "$SELECTED" == *"nyxt"*           ]] && SUMMARY+="  ✦ Nyxt\n"
[[ "$SELECTED" == *"librewolf"*      ]] && SUMMARY+="  ✦ LibreWolf\n"
[[ "$SELECTED" == *"min-browser"*    ]] && SUMMARY+="  ✦ Min Browser\n"
[[ "$SELECTED" == *"vscodium"*       ]] && SUMMARY+="  ✦ VSCodium\n"
[[ "$SELECTED" == *"zed-ide"*        ]] && SUMMARY+="  ✦ Zed IDE\n"
[[ "$SELECTED" == *"geany"*          ]] && SUMMARY+="  ✦ Geany\n"
[[ "$SELECTED" == *"codeblocks"*     ]] && SUMMARY+="  ✦ Code::Blocks\n"
[[ "$SELECTED" == *"kate"*           ]] && SUMMARY+="  ✦ Kate\n"

dialog --backtitle "$BACKTITLE" \
    --title " Confirm " \
    --yesno "\n  Modules to install:\n\n${SUMMARY}\n  Log: $LOG\n\n  Proceed?" \
    30 64 || { clear; echo "Aborted."; exit 0; }

count_steps "$SELECTED"

DE_DIR="$MODULES/Desktop-Environments"
[[ "$SELECTED" == *"kde-plasma"*     ]] && run_module "KDE Plasma"         "$DE_DIR/kde-plasma.sh"
[[ "$SELECTED" == *"gnome"*          ]] && run_module "GNOME"              "$DE_DIR/gnome.sh"
[[ "$SELECTED" == *"cosmic"*         ]] && run_module "COSMIC"             "$DE_DIR/cosmic.sh"
[[ "$SELECTED" == *"niri"*           ]] && run_module "Niri"               "$DE_DIR/niri.sh"
[[ "$SELECTED" == *"xfce"*           ]] && run_module "XFCE"              "$DE_DIR/xfce.sh"
[[ "$SELECTED" == *"lxqt"*           ]] && run_module "LXQt"              "$DE_DIR/lxqt.sh"
[[ "$SELECTED" == *"ollama"*         ]] && run_module "Ollama"            "$APPS/ollama.sh"
[[ "$SELECTED" == *"llama-cpp"*      ]] && run_module "llama.cpp"         "$APPS/llama-cpp.sh"
[[ "$SELECTED" == *"open-webui"*     ]] && run_module "Open WebUI"        "$APPS/open-webui.sh"
[[ "$SELECTED" == *"claude"*         ]] && run_module "Claude Code"       "$APPS/claude.sh"
[[ "$SELECTED" == *"anti-malware"*   ]] && run_module "Anti-Malware"      "$APPS/anti-malware.sh"
[[ "$SELECTED" == *"networking-cli"* ]] && run_module "Networking CLI"    "$APPS/networking-cli.sh"
[[ "$SELECTED" == *"disk-recovery"*  ]] && run_module "Disk Recovery"     "$APPS/disk-recovery.sh"
[[ "$SELECTED" == *"himalaya"*       ]] && run_module "Himalaya"          "$APPS/himalaya.sh"
[[ "$SELECTED" == *"gnuplot"*        ]] && run_module "Gnuplot"           "$APPS/gnuplot.sh"
[[ "$SELECTED" == *"povray"*         ]] && run_module "POV-Ray"           "$APPS/povray.sh"
[[ "$SELECTED" == *"blender"*        ]] && run_module "Blender"           "$APPS/blender.sh"
[[ "$SELECTED" == *"toot"*           ]] && run_module "toot"              "$APPS/toot.sh"
[[ "$SELECTED" == *"db-clients"*     ]] && run_module "DB Clients"        "$APPS/db-clients.sh"
[[ "$SELECTED" == *"mysql"*          ]] && run_module "MySQL / MariaDB"   "$APPS/mysql.sh"
[[ "$SELECTED" == *"productivity"*   ]] && run_module "Productivity"      "$APPS/productivity.sh"
[[ "$SELECTED" == *"yt-dlp"*         ]] && run_module "yt-dlp"           "$APPS/yt-dlp.sh"
[[ "$SELECTED" == *"sox"*            ]] && run_module "SoX"              "$APPS/sox.sh"
[[ "$SELECTED" == *"imagemagick"*    ]] && run_module "ImageMagick"       "$APPS/imagemagick.sh"
[[ "$SELECTED" == *"ffmpeg"*         ]] && run_module "FFmpeg extras"     "$APPS/ffmpeg.sh"
[[ "$SELECTED" == *"localtunnel"*    ]] && run_module "LocalTunnel"       "$APPS/localtunnel.sh"
[[ "$SELECTED" == *"butter"*          ]] && run_module "butter"            "$APPS/butter.sh"
[[ "$SELECTED" == *"plymouth"*        ]] && run_module "Plymouth"                "$APPS/plymouth.sh"
if [[ "$SELECTED" == *"plymouth-custom"* ]]; then
    export PLYMOUTH_LOGO_SRC
    run_module "Plymouth (custom)" "$APPS/plymouth-custom.sh"
fi
[[ "$SELECTED" == *"greetd-regreet"* ]] && run_module "greetd + ReGreet" "$APPS/greetd-regreet.sh"
[[ "$SELECTED" == *"lightdm"*        ]] && run_module "LightDM greeter"   "$APPS/lightdm.sh"
# 'ly' is padded/quote-stripped so it doesn't substring-match 'p(ly)mouth'.
[[ " ${SELECTED//\"/} " == *" ly "*  ]] && run_module "ly greeter"        "$APPS/ly.sh"
[[ "$SELECTED" == *"tlp"*            ]] && run_module "TLP"               "$APPS/tlp.sh"
[[ "$SELECTED" == *"steam"*          ]] && run_module "Steam"             "$APPS/steam.sh"
[[ "$SELECTED" == *"vesktop"*        ]] && run_module "Vesktop"           "$APPS/vesktop.sh"
[[ "$SELECTED" == *"spotify"*        ]] && run_module "Spotify"           "$APPS/spotify.sh"
[[ "$SELECTED" == *"prism"*          ]] && run_module "PrismLauncher"     "$APPS/prismlauncher.sh"
[[ "$SELECTED" == *"vintagestory"*   ]] && run_module "Vintage Story"     "$APPS/vintagestory.sh"
[[ "$SELECTED" == *"openarena"*      ]] && run_module "OpenArena"         "$APPS/openarena.sh"
[[ "$SELECTED" == *"tetris"*         ]] && run_module "Tetris CLI"        "$APPS/tetris.sh"
[[ "$SELECTED" == *"doom"*           ]] && run_module "Doom"              "$APPS/doom.sh"
[[ "$SELECTED" == *"sauerbraten"*    ]] && run_module "Sauerbraten"       "$APPS/sauerbraten.sh"
[[ "$SELECTED" == *"stuntrally"*     ]] && run_module "Stunt Rally"       "$APPS/stuntrally.sh"
[[ "$SELECTED" == *"localsend"*      ]] && run_module "LocalSend"         "$APPS/localsend.sh"
[[ "$SELECTED" == *"croc"*           ]] && run_module "croc"              "$APPS/croc.sh"
[[ "$SELECTED" == *"onlyoffice"*     ]] && run_module "OnlyOffice"        "$APPS/onlyoffice.sh"
[[ "$SELECTED" == *"wireshark"*      ]] && run_module "Wireshark"         "$APPS/wireshark.sh"
[[ "$SELECTED" == *"k8s"*            ]] && run_module "Kubernetes Tools"  "$APPS/k8s.sh"
[[ "$SELECTED" == *"docker"*         ]] && run_module "Docker"            "$APPS/docker.sh"
[[ "$SELECTED" == *"podman"*         ]] && run_module "Podman"            "$APPS/podman.sh"
[[ "$SELECTED" == *"cockpit"*        ]] && run_module "Cockpit"           "$APPS/cockpit.sh"
[[ "$SELECTED" == *"ssh-server"*     ]] && run_module "SSH Server"        "$APPS/ssh-server.sh"
[[ "$SELECTED" == *"freeipa-client"* ]] && run_module "FreeIPA Client"    "$APPS/freeipa-client.sh"
[[ "$SELECTED" == *"freeipa-server"* ]] && run_module "FreeIPA Server"    "$APPS/freeipa-server.sh"
[[ "$SELECTED" == *"freeipa-image"*  ]] && run_module "FreeIPA Image"     "$APPS/freeipa-image-builder.sh"
[[ "$SELECTED" == *"python"*         ]] && run_module "Python Tools"      "$MODULES/optional-Modules/python.sh"
[[ "$SELECTED" == *"zfs"*            ]] && run_module "ZFS"              "$MODULES/optional-Modules/zfs.sh"
[[ "$SELECTED" == *"wprs"*           ]] && run_module "WPRS"             "$MODULES/optional-Modules/wprs.sh"
[[ "$SELECTED" == *"chromium"*       ]] && run_module "Chromium"         "$APPS/chromium.sh"
[[ "$SELECTED" == *"firefox-browser"* ]] && run_module "Firefox"         "$APPS/firefox.sh"
[[ "$SELECTED" == *"zen-browser"*    ]] && run_module "Zen Browser"      "$APPS/zen-browser.sh"
[[ "$SELECTED" == *"nyxt"*           ]] && run_module "Nyxt"             "$APPS/nyxt.sh"
[[ "$SELECTED" == *"librewolf"*      ]] && run_module "LibreWolf"        "$APPS/librewolf.sh"
[[ "$SELECTED" == *"min-browser"*    ]] && run_module "Min Browser"      "$APPS/min-browser.sh"
[[ "$SELECTED" == *"vscodium"*       ]] && run_module "VSCodium"         "$APPS/vscodium.sh"
[[ "$SELECTED" == *"zed-ide"*        ]] && run_module "Zed IDE"          "$APPS/zed.sh"
[[ "$SELECTED" == *"geany"*          ]] && run_module "Geany"            "$APPS/geany.sh"
[[ "$SELECTED" == *"codeblocks"*     ]] && run_module "Code::Blocks"     "$APPS/codeblocks.sh"
[[ "$SELECTED" == *"kate"*           ]] && run_module "Kate"             "$APPS/kate.sh"

dialog --backtitle "$BACKTITLE" \
    --title " Done " \
    --msgbox "\n  All selected modules installed.\n\n  Log: $LOG\n\n  A reboot may be required for some changes.\n" 11 56

clear
printf "\n  Done. Log: %s\n\n" "$LOG"
