#!/bin/bash -e
#
# Author: Casey DeLorme
#
# Description: fully automate installation and config after `arch-chroot`,
# providing the user with a fully configured desktop environment and many
# bells and whistles for developers.
#
# Dependencies: requires `base` and `base-devel` be installed with `pacstrap`,
# and runs as root.  Expects `username`, `password`, and `root_password` to be
# supplied.

# verify required variables
while [ -z "$root_password" ]; do read -p "please enter a root password: " -s root_password && echo ""; done
while [ -z "$username" ]; do read -p "please enter your username: " username; done
while [ -z "$password" ]; do read -p "please enter your password: " -s password && echo ""; done

# print all that transpires henceforth
[ -n "$DEBUG" ] && set -x

# initial time configuration
ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
hwclock -w --utc

# setup locale
sed -i "/^en_US.UTF-8/d" /etc/locale.gen
sed -i "/^ja_JP.UTF-8/d" /etc/locale.gen
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
echo "ja_JP.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf

# setup hostname
echo "${hostname:-arch}" > /etc/hostname
echo "127.0.0.1 localhost" > /etc/hosts
echo "::1 localhost" >> /etc/hosts
echo "127.0.1.1 $(cat /etc/hostname).localdomain $(cat /etc/hostname)" >> /etc/hosts

# set default virtualconsole font
setfont koi8u_8x16
echo "FONT=koi8u_8x16" > /etc/vconsole.conf

# enable multilib
sed -i "/\[multilib\]/,/Include/"'s/^#//' /etc/pacman.conf

# rebuild gpg keys
rm -rf /etc/pacman.d/gnupg
pacman-key --init
pacman-key --populate archlinux

# Core tools
export PACKAGES="linux linux-headers linux-firmware base-devel mkinitcpio sudo bash-completion man-db tmux gvim dkms dmidecode at bc cronie lm_sensors lshw stress memtest86+ memtest86+-efi"

# install core packages so dependencies exist
pacman -Syu --noconfirm $PACKAGES

# Conditional CPU unicode
[ $(grep -c "Intel" /proc/cpuinfo) -gt 0 ] && PACKAGES="${PACKAGES} intel-ucode"
[ $(grep -c "AMD" /proc/cpuinfo) -gt 0 ] && PACKAGES="${PACKAGES} amd-ucode"

# Conditional battery packages
[ -e /sys/class/power_supply/BAT0 ] && PACKAGES="${PACKAGES} xf86-input-synaptics acpid tlp"

# Storage
PACKAGES="${PACKAGES} btrfs-progs smartmontools usbutils gvfs gvfs-mtp gvfs-afc android-udev parted postgresql transmission-cli python-pip python-setuptools"

# Compression
PACKAGES="${PACKAGES} cryptsetup lzop unzip p7zip xz unrar unace lrzip arj innoextract"

# networking packages
PACKAGES="${PACKAGES} nftables iptables dnsmasq rsync dhcpcd inetutils net-tools openssh sshfs ntp wget curl wireless_tools bluez bluez-utils oath-toolkit openconnect openvpn ethtool pptpclient connman wpa_supplicant iwd"

# programming packages
PACKAGES="${PACKAGES} pkgfile pkgconf bison gcc gcc-libs cmake ccache ncurses lib32-ncurses xmlstarlet jq git mercurial subversion bzr patchelf xdelta3 packer libvirt qemu qemu-base qemu-desktop qemu-full libguestfs virt-install edk2-ovmf gnutls lib32-gnutls libgpg-error lib32-libgpg-error sqlite lib32-sqlite libgcrypt lib32-libgcrypt ocl-icd lib32-ocl-icd llvm lib32-llvm llvm-libs lib32-llvm-libs"

# multimedia dependencies
PACKAGES="${PACKAGES} mesa lib32-mesa dbus polkit giflib lib32-giflib mpg123 lib32-mpg123 v4l-utils lib32-v4l-utils lame libwebp libid3tag libvorbis vorbis-tools faac x264 x265 libldap lib32-libldap libpng lib32-libpng libjpeg-turbo lib32-libjpeg-turbo pipewire lib32-pipewire pipewire-jack lib32-pipewire-jack pipewire-alsa pipewire-pulse pipewire-zeroconf wireplumber openal lib32-openal alsa-plugins lib32-alsa-plugins alsa-lib lib32-alsa-lib opencl-icd-loader lib32-opencl-icd-loader libva lib32-libva libva-utils gst-plugins-base-libs graphicsmagick imagemagick joyutils evtest libexif ffmpeg yt-dlp wine-staging winetricks fcitx5 fcitx5-mozc fcitx5-configtool fcitx5-gtk fcitx5-qt"

# GUI theme
PACKAGES="${PACKAGES} gnome-themes-extra hicolor-icon-theme"

# GUI dependencies
PACKAGES="${PACKAGES} gtk3 lib32-gtk3 pavucontrol pcmanfm ffmpegthumbnailer tumbler xdg-utils xdg-user-dirs libxcomposite lib32-libxcomposite libxinerama lib32-libxinerama libxslt lib32-libxslt"

# vulkan packages
PACKAGES="${PACKAGES} libva-mesa-driver lib32-libva-mesa-driver vulkan-tools vulkan-icd-loader lib32-vulkan-icd-loader vulkan-headers vulkan-validation-layers lib32-vulkan-validation-layers vulkan-mesa-layers lib32-vulkan-mesa-layers"

# Sway dependencies
PACKAGES="${PACKAGES} sway swaybg alacritty wofi waybar xorg-xwayland xorg-xlsclients wev qt5-wayland glfw-x11 grim slurp xdg-desktop-portal-wlr libpipewire lib32-libpipewire wl-clipboard brightnessctl playerctl mako libappindicator-gtk3 lib32-libappindicator-gtk3"

# fonts
PACKAGES="${PACKAGES} fontconfig ttf-bitstream-vera ttf-droid ttf-dejavu ttf-liberation ttf-jigmo ttf-roboto ttf-sazanami ttf-vlgothic ttf-font-awesome otf-font-awesome"

# GUI software
PACKAGES="${PACKAGES} xarchiver gparted psensor steam gamemode gamescope mangohud lib32-mangohud lib32-gamemode discord mpv mpv-mpris gimp krita obs-studio mednafen mame ppsspp lutris neovim evince virt-manager virtualbox virtualbox-host-modules-arch"

# conditional AMD GPU packages
if [ $(lspci | grep -i "vga" | grep -ci "amd") -gt 0 ]; then
	PACKAGES="${PACKAGES} xf86-video-amdgpu vulkan-radeon lib32-vulkan-radeon"

	# update modules to load
	[ $(grep -c "amd" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 amdgpu radeon)/' /etc/mkinitcpio.conf
fi

# conditional Intel GPU packages
if [ $(lspci | grep -i "vga" | grep -ci "intel") -gt 0 ]; then
	PACKAGES="${PACKAGES} xf86-video-intel vulkan-intel lib32-vulkan-intel mesa-vdpau"

	# update modules to load
	[ $(grep -c "amd" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 i915)/' /etc/mkinitcpio.conf
fi

# conditional nVidia GPU packages
# @note: untested since 2019; I stopped using nvidia
if [ $(lspci | grep -i "vga" | grep -ci "nvidia") -gt 0 ]; then
	PACKAGES="${PACKAGES} nvidia-dkms libglvnd lib32-libglvnd opencl-nvidia lib32-opencl-nvidia xf86-video-nouveau nvidia-utils lib32-nvidia-utils mesa-vdpau nvidia-settings"

	# update modules to load
	[ $(grep -c "nvidia" /etc/mkinitcpio.conf) -eq 0 ] && sed -i 's/MODULES=(\(.*\))/MODULES=(\1 nvidia nvidia_modeset nvidia_uvm nvidia_drm)/' /etc/mkinitcpio.conf

	# automatic mkinitcpio updates in pacman.d
	mkdir -p /etc/pacman.d/hooks
	echo -e "[Trigger]\nOperation=Install\nOperation=Upgrade\nOperation=Remove\nType=Package\nTarget=nvidia\n\n[Action]\nDepends=mkinitcpio\nWhen=PostTransaction\nExec=/usr/bin/mkinitcpio -P" > /etc/pacman.d/hooks/nvidia.hook
fi

# install all packages
pacman -Syu --noconfirm $PACKAGES

# install base configuration files from repository
[ -d /srv/arch-desktop/install ] || git clone https://git.caseydelorme.com/cdelorme/arch-desktop /srv/arch-desktop
rsync -Pav /srv/arch-desktop/install/ /
mkdir -p /etc/skel/{desktop,downloads,public,public/templates,documents,music,pictures/{wallpaper,screenshots},videos,code/aur.archlinux.org}
rsync -Pav /etc/skel/ "$(getent passwd root | cut -d: -f6)/"
sed -i "/ssh-add/d" "$(getent passwd root | cut -d: -f6)/.bashrc"

# symlink scheduled maintenance tasks
#ln -sf /usr/local/bin/system-updates /etc/cron.daily/system-updates
ln -sf /usr/local/bin/disk-maintenance /etc/cron.weekly/disk-maintenance

# symlink override vi to vim
ln -sf /usr/bin/vim /usr/local/bin/vi

# enable ccache and optimize cores for AUR
sed -i 's/!ccache/ccache/' /etc/makepkg.conf
sed -i 's/^#MAKEFLAGS.*/MAKEFLAGS="-j$(($(nproc) + 1)) -l$(nproc)"/' /etc/makepkg.conf

# create sudo group
groupadd -fr sudo

# temporarily make sudo passwordless for automation
echo '%sudo ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/sudo

# update font cache
fc-cache -fr

# secure ssh by disabling root access and only accepting ssh keys
sed -i "/^#\?PermitRootLogin/d" /etc/ssh/sshd_config
sed -i "/^#\?PasswordAuthentication/d" /etc/ssh/sshd_config
sed -i "/^#\?X11Forwarding/d" /etc/ssh/sshd_config
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
echo "X11Forwarding yes" >> /etc/ssh/sshd_config

# set journald size
sed -i '/^SystemMaxUse/d' /etc/systemd/journald.conf
echo "SystemMaxUse=2G" >> /etc/systemd/journald.conf

# set root password
printf "${root_password}\n${root_password}\n" | passwd

# initialize postgres database
su - postgres -c "initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'"

# create configuration to fix transmission errors
echo "net.core.rmem_max = 4194304" > /etc/sysctl.d/transmission.conf
echo "net.core.wmem_max = 1048576" >> /etc/sysctl.d/transmission.conf

# create user if not exists, else (re)-install dot-files
if ! id $username &> /dev/null; then
	useradd -m -s /bin/bash $username
	echo "${username}:${password}" | chpasswd -c SHA256
else
	[ $EUID -ne 0 ] && rsync -Pav /etc/skel/ "$(getent passwd $username | cut -d: -f6)/"
fi

# add user to standard groups
usermod -aG users,sudo,adm,input,audio,video,disk,storage,lp,vboxusers $username

# generate postgres user and user database
systemctl start postgresql
su postgres -c "cd && createuser -ds $username" 2> /dev/null && su $username -c "cd && createdb"

# load xdg-user-dirs
su $username -c "cd && xdg-user-dirs-update"
update-desktop-database

# generate default (passwordless) ed25519 ssh key if none exists
su $username -c "cd; if [ ! -f ~/.ssh/id_ed25519 ]; then ssh-keygen -q -t ed25519 -N '' -f ~/.ssh/id_ed25519 && cd && chmod 600 ~/.ssh/id_ed25519 && chmod 600 ~/.ssh/id_ed25519.pub; fi"

# install gvm loading from ~/.bashrc & ~/.bash_profile, and the latest go version
su $username -c "if [ ! -d ~/.gvm ]; then GVM_NO_UPDATE_PROFILE=1 bash < <(curl -Ls https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer 2> /dev/null); fi"
su $username -c 'grep "gvm" ~/.bash_profile &> /dev/null || echo -e "\n# load gvm\n[ -s $HOME/.gvm/scripts/gvm ] && . $HOME/.gvm/scripts/gvm" >> ~/.bash_profile'
su $username -c ". ~/.gvm/scripts/gvm && gvm install go1.26.1 -B && gvm use go1.26.1 --default"
# @note: fix stupid fucking cd override in gvm scripts
su $username -c "[ -f ~/.gvm/scripts/env/cd ] && mv ~/.gvm/scripts/env/cd ~/.gvm/scripts/env/cd.bak && touch ~/.gvm/scripts/env/cd"

# configure user-space transmission
if [ ! -f "/etc/systemd/system/transmission.service.d/local.conf" ]; then
	su $username -c "cd && mkdir -p ~/transmission/{done,incomplete}"
	su $username -c 'cd && tmp=$(mktemp) && jq ".[\"download-dir\"] = \"${HOME}/transmission/done\"" $HOME/.config/transmission-daemon/settings.json | jq ".[\"incomplete-dir\"] = \"${HOME}/transmission/incomplete\"" | jq ".[\"watch-dir\"] = \"$(xdg-user-dir DOWNLOAD)\"" > $tmp && mv $tmp $HOME/.config/transmission-daemon/settings.json'
fi

# consolidate paths for aur
export user_home="$(getent passwd $username | cut -d: -f6)/"
export aur_home="${user_home}aur.archlinux.org/"

# install qview
sudo -u $username git clone https://aur.archlinux.org/qview.git ${aur_home}qview
(cd ${aur_home}qview && sudo -u ${username} makepkg -rcsi --noconfirm)

# cmst (for connman UI)
sudo -u $username git clone https://aur.archlinux.org/cmst.git ${aur_home}cmst
(cd ${aur_home}cmst && sudo -u ${username} makepkg -rcsi --noconfirm)

# brave browser (plus override to bypass keyring)
sudo -u $username git clone https://aur.archlinux.org/brave-bin.git ${aur_home}brave-bin
(cd ${aur_home}brave-bin && sudo -u ${username} makepkg -rcsi --noconfirm)
[ -f /usr/share/applications/brave-browser.desktop ] && sed -i 's|Exec=brave|Exec=brave --password-store=basic|g' /usr/share/applications/brave-browser.desktop

# install vimix-cursors
sudo -u $username git clone https://aur.archlinux.org/vimix-cursors.git ${aur_home}vimix-cursors
(cd ${aur_home}vimix-cursors && sudo -u ${username} makepkg -rcsi --noconfirm)

# install numix-icon-theme
sudo -u $username git clone https://aur.archlinux.org/numix-icon-theme-git.git ${aur_home}numix-icon-theme-git
(cd ${aur_home}numix-icon-theme-git && sudo -u ${username} makepkg -rcsi --noconfirm)

# restore password requirement to sudo group
echo '%sudo ALL=(ALL) ALL' > /etc/sudoers.d/sudo

# enable services for next reboot
which acpid &> /dev/null && systemctl enable acpid
which tlp &> /dev/null && systemctl enable tlp
systemctl enable postgresql
systemctl enable bluetooth
systemctl enable nftables
systemctl enable libvirtd
systemctl enable dnsmasq
systemctl enable cronie
systemctl enable systemd-timesyncd
systemctl enable sshd
systemctl enable connman

# attempt to enable dhcp on active network devices on reboot
export active_network_device=$(ip addr | awk '/state UP/ {print $2}' | sed 's/.$//')
[ ! -d "/sys/class/net/${active_network_device}/wireless" ] && (systemctl enable dhcpcd@${active_network_device} || echo "failed to enable dhcp service")

# (re)build vmlinux image
mkinitcpio -p linux

# install the bootloader
bootctl install

# create boot loader entry
echo "title arch" > /boot/loader/entries/arch.conf
echo "linux vmlinuz-linux" >> /boot/loader/entries/arch.conf
echo "title memtest" > /boot/loader/entries/memtest.conf
echo "efi /memtest86+/memtest.efi" >> /boot/loader/entries/memtest.conf
[ -f /boot/intel-ucode.img ] && echo "initrd /intel-ucode.img" >> /boot/loader/entries/arch.conf
[ -f /boot/amd-ucode.img ] && echo "initrd /amd-ucode.img" >> /boot/loader/entries/arch.conf
echo "initrd /initramfs-linux.img" >> /boot/loader/entries/arch.conf
export boot_options="options root=PARTUUID=$(blkid -s PARTUUID -o value $(mount | grep ' / '|cut -d' ' -f 1)) rw quiet loglevel=3"
[ "$enable_hibernation" = "y" ] && [ -n "$resume_uuid" ] && boot_options="${boot_options} resume=UUID=${resume_uuid}"
[[ $(lspci | grep -i " vga" | grep -ci " nvidia") -gt 0 && $(grep -c "nvidia" /boot/loader/entires/arch.conf) -eq 0 ]] && boot_options="${boot_options} nvidia-drm.modeset=1"
echo "$boot_options" >> /boot/loader/entries/arch.conf

# set boot loader entry as default
sed -i '/^default/d' /boot/loader/loader.conf
echo "default arch.conf" >> /boot/loader/loader.conf

# remove resolv.conf since connman is wierd ???
rm -f /etc/resolv.conf || echo "ignore failed removal; a task left to the user..."

# check boot loader configuration
bootctl status

# cleanup pacman cache to minimize image
yes | pacman -Scc
sync
