#!/usr/bin/env bash

## An idempotent system configuration script for my personal laptop.
##
## Usage: configure
##
## Dependencies: Fedora 43
##
## I run this script after performing a minimal installation of Fedora Linux (no
## desktop environment) and I run it daily thereafter.

set -euo pipefail
shopt -s inherit_errexit

die() { echo "${0##*/}: $1" >&2; exit 1; }

[[ " $* " =~ ' --help ' ]] && sed -n 's/^## \?//p' "$0" && exit
(( $# )) && die 'invalid argument'
(( UID )) || die 'do not run as root'

# Add user to groups.
sudo gpasswd -a "$USER" lp
echo

# Create directories.
mkdir -p ~/{.cache,.local/{bin,share,state},.opt,pending}
sudo mkdir -p /media/{cdrom,samsung-128gb,wd-25a2-2tb,wd-25e2-2tb-{1,2}}

# Add file systems to fstab and mount them.
fstab_contents=$(< /etc/fstab)
fstab_update=$(cat <<-EOF
	UUID=48f7a023-824c-4e34-bc79-fb95ffd767c4 /media/wd-25a2-2tb   ext4  nofail,noatime 0 2
	UUID=0f7ada7d-8766-4712-8cea-d010a98f5437 /media/wd-25e2-2tb-1 ext4  nofail,noatime 0 2
	UUID=f1f754ca-6f6b-42ae-a037-c25a1fd6a253 /media/wd-25e2-2tb-2 btrfs nofail,noatime 0 2
	UUID=7746-0C3C                            /media/samsung-128gb exfat nofail         0 0
	/dev/sr0                                  /media/cdrom         auto  nofail,ro,user 0 0
	EOF
)
if [[ ! $fstab_contents =~ $fstab_update ]]; then
  echo 'Adding file systems to fstab and mounting them'
  sudo tee -a /etc/fstab <<< "$fstab_update" > /dev/null
  sudo systemctl daemon-reload # Must be run after modifying fstab.
  sudo mount -a
  echo
fi

# Restore files from backup.
if [[ ! -d ~/main ]]; then
  if [[ -d /media/wd-25e2-2tb-2/backups/latest ]]; then
    backup=/media/wd-25e2-2tb-2/backups/latest
  elif [[ -d /mnt/main ]]; then
    backup=/mnt # The backup I restore when testing this script on a VM.
  else
    die 'backup not found'
  fi
  echo 'Restoring files from backup'
  cp -aT "$backup" ~
  [[ $backup == /media/cdrom ]] && chmod -R +rw ~
  echo
fi

# Configure DNF.
dnfconf_contents=$(< /etc/dnf/dnf.conf)
dnfconf_update='install_weak_deps=False'
if [[ ! $dnfconf_contents =~ $dnfconf_update ]]; then
  sudo tee -a /etc/dnf/dnf.conf <<< "$dnfconf_update" > /dev/null
fi

echo 'Upgrading RPMs'
sudo dnf upgrade
echo

echo "Installing RPMs from Fedora's main package repository"
fedora_rpms=(
  altermime chromium-browser cups dunst emacs-lucid evince fd-find feh
  ffmpeg-free fontconfig fzf gimp git google-noto-emoji-fonts gpick ImageMagick
  imv imwheel maildir-utils nodejs openbox oxipng pass pdfgrep pipewire
  pipewire-pulseaudio pnpm printer-driver-brlaser qemu-img qemu-system-x86
  ripgrep rsms-inter-fonts rsync sane-backends scrot ShellCheck sqlite sysstat
  tar unzip virtiofsd xclip xdg-utils xinput xorg-x11-server-Xorg xorg-x11-xauth
  xorg-x11-xinit xsel xterm yamllint
)
sudo dnf install -y "${fedora_rpms[@]}"
echo

if ! type google-chrome &> /dev/null; then
  echo 'Installing Chrome using the RPM from Google'
  curl -f --output=/tmp/chrome.rpm \
    https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
  sudo dnf install /tmp/chrome.rpm
  echo
fi

# Install Firefox using Mozilla's binary because Fedora's package repositories
# often lack the latest version.
if ! type firefox &> /dev/null; then
  echo "Installing Firefox using Mozilla's binary"
  curl -fL --output=/tmp/firefox.tar.bz2 \
    'https://download.mozilla.org/?product=firefox-latest-ssl&os=linux64'
  tar -x --file=/tmp/firefox.tar.bz2 --directory=~/.opt
  ln -s ~/.opt/firefox/firefox ~/.local/bin/firefox
  echo 'Installing runtime dependencies for Firefox'
  sudo dnf install dbus-glib
  echo
fi

# Install Node.js packages globally if there are no alternatives in Fedora's
# package repositories and if these Node.js packages can't be used via dev VMs,
# which is where I normally run Node.js packages to limit the potential damage
# of malware. These Node.js packages are the only reason I install Node.js
# outside of dev VMs.
echo 'Installing Node.js packages globally'
pnpm add -g prettier typescript-language-server
echo

# Remove pnpm to avoid installing or running additional Node.js packages outside
# of dev VMs.
echo 'Removing pnpm'
sudo dnf remove -y pnpm
echo

echo 'Removing RPMs that were dependencies but are no longer required'
sudo dnf autoremove
echo

echo 'Removing unwanted files'
rm -f ~/.bash_history # HISTFILE variable is set to a different path.
rm -fr ~/.local/share/Trash # Files "deleted" by certain apps.
echo

echo 'Disabling unneeded services'
sudo systemctl disable avahi-daemon # Mostly used for network printers?
sudo systemctl disable cups # I manually start the CUPS service when needed.
echo

# Initialize mu's message database and then index messages in my maildir.
if ! mu info &> /dev/null; then
  echo "Initializing mu's message database and indexing messages"
  mu_init_opts=(--maildir="$HOME"/main/m/maildir)
  mapfile -t my_addresses < ~/main/m/maildir/my-addresses
  for line in "${my_addresses[@]}"; do
    [[ $line =~ @ ]] && mu_init_opts+=(--my-address="$line")
  done
  mu init "${mu_init_opts[@]}"
  mu index
fi
