#!/bin/bash

# Environments
LAPTOP="laptop"
DESKTOP="desk"
ENV_EXT_REGEXP=".*\.${LAPTOP}|.*\.${DESKTOP}"

# Special filename for external config path
DEST_FILENAME="dest"

# Special configuration filename
BASE_CONFIG="config_common"
MERGE_CONFIG_FOLDER="config.d"
FINAL_CONFIG="config"

# Special directories with per-environment configuration merge
I3_CONFIG="i3"
POLYBAR_CONFIG="polybar"
ARCH_PACKAGES="bootstrap"
MERGE_DIRS="${I3_CONFIG} ${POLYBAR_CONFIG} ${ARCH_PACKAGES}"

changed_files="$(git --git-dir=$HOME/.cfg/ --work-tree=$HOME diff-tree -r --name-status --no-commit-id HEAD^1 HEAD)"

# Check if a file has been modified and deleted since last commit, if so perform an action
# $1 : absolute path of the file
# $2 : command to launch if file has been created of modifed
# $3 : command to launch if file has been deleted
function check_copy() {
	# When initializing, always copy files
	if [ ! -z ${INIT} ]; then
		echo -e "* Running \"$2\"" && eval "$2"
		return
	fi
	changed_file=`grep "${1#$HOME/}" <<< "${changed_files}"`
	if [ ! -z "${changed_file}" ]; then
		if echo "$changed_file" | grep -q -E "^D"; then
			echo "* $1 has been removed"
			echo -e "\t* Running \"$3\"" && eval "$3"
		fi
		if echo "$changed_file" | grep -q -E "^(A|M)"; then
			echo "* Changes detected in $(basename $1)"
			echo -e "\t* Running \"$2\"" && eval "$2"
		fi
	else
		echo "$1 not modified, no need to copy"
	fi
}

# Generates a `config` file in $1, by merging a required $1/{MERGE_CONFIG_FOLDER} file
# with an optional `$1/config.d/$2` file. This is useful for having
# a common base for multiple computer, and per-computer stuff.
# $1 : path of the folder 
# $2 : current environment
# $3 : if defined, prepend $2 instead of appending
function merge_config() {
	echo -e "\n=== Generate ${m} config file ==="
	final_path=${CONFIG}/${m}/${FINAL_CONFIG}.${2}
	rm -f ${final_path}
	# Copy common config
	cp ${CONFIG}/${m}/${BASE_CONFIG} ${final_path}
	echo "${final_path} created"
	# If there is an override folder, merge given env
	if [ ! -z ${2} ] && [ -d ${CONFIG}/${m}/${MERGE_CONFIG_FOLDER} ]; then
		for f in `find ${CONFIG}/${m}/config.d -type f -path "*${2}"`; do
			if [ -z $3 ]; then 
				echo "Found ${f}, append to regular config file"
				echo -e "\n$(cat ${f})\n" >> ${final_path}
			else
				echo "Found ${f}, prepend to regular config file"
				echo -e "\n$(cat ${f})\n$(cat ${final_path})\n" > ${final_path}
			fi
		done
	fi
}

function usage() {
	echo "${0}: manage package installation, environment divergence and external location for config, see README."
	echo "usage: [WM_RESTART=1] [INIT=1] $0 [${ENVIRONMENTS}]"
	exit 0
}

function init_system() {
	echo -e "* Installing base Arch packages..."
	yay -Syu --needed --noconfirm - < ${CONFIG}/${ARCH_PACKAGES}/${FINAL_CONFIG}
	echo -e "* Changing shell to ZSH..."
	chsh -s $(which zsh)
	if [ "$ENV" = "desk" ]; then
		echo -e "* Add user to realtime group..."
		sudo usermod -aG realtime $(whoami)
	fi
	# https://man.archlinux.org/man/rofi-dmenu.5
	echo -e "* Symlink dmenu → rofi..."
	sudo ln -sf /usr/bin/rofi /usr/bin/dmenu
	echo -e "* Enabling common systemd units..."
	sudo systemctl enable --now systemd-timesyncd
	sudo systemctl enable --now cups
	sudo systemctl enable --now bluetooth
	sudo systemctl enable --now bluetooth-autoconnect
	sudo systemctl enable --now updatedb.timer
	systemctl --user enable --now pipewire-pulse
	systemctl --user enable --now pipewire-pulse.socket
	echo -e "* Enable resolvctl..."
	sudo systemctl enable --now systemd-resolved
	sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
	~/.config/bootstrap/init_netctl.sh ${ENV}
	echo -e "* Ensure hardware clock is up to date..."
	sudo hwclock --systohc
	# So that "Open in Terminal" works inc Nemo
	echo -e "* Make 'Open Terminal' work in Nemo..."
	sudo gsettings set org.cinnamon.desktop.default-applications.terminal exec i3-sensible-terminal
	# For screenshots
	echo -e "* Install pychee for uploading screenshots on Lychee..."
	pip install --break-system-packages pychee
	# Additionnal plugins for ZSH
	echo -e "* Install ZSH plugins for oh-my-zsh..."
	sudo git clone https://github.com/zdharma-continuum/fast-syntax-highlighting.git /usr/share/oh-my-zsh/plugins/fast-syntax-highlighting
	sudo git clone https://github.com/zsh-users/zsh-autosuggestions /usr/share/oh-my-zsh/plugins/zsh-autosuggestions
	sudo git clone https://github.com/unixorn/fzf-zsh-plugin.git /usr/share/oh-my-zsh/plugins/fzf-zsh-plugin
	echo -e "* Install everything we need for Catppuccin themes..."
	echo -e "\tFor polybar..."
	wget https://raw.githubusercontent.com/catppuccin/polybar/main/themes/macchiato.ini -O ~/.config/polybar/macchiato.ini
	echo -e "\tFor zsh..."
	sudo mkdir -p /usr/local/share/fsh
	sudo wget https://raw.githubusercontent.com/catppuccin/zsh-fsh/main/themes/catppuccin-macchiato.ini -O /usr/local/share/fsh/catppuccin-macchiato.ini
	echo -e "\tFor gtk..."
	# Change icon color for Papirus Icon Theme
	papirus-folders -C cat-latte-flamingo --theme Papirus-Dark
	echo -e "\tFor Pygments..."
	pip install --break-system-packages 'catppuccin[pygments]'
	# Basic directory structure
	echo -e "* Create base home directories..."
	mkdir -p ~/documents ~/images/screenshots ~/videos ~/downloads
	echo -e "* Allow user to control brightness..."
	sudo usermod $(whoami) -aG video
	echo -e "* Allow user to administrate printers..."
	sudo usermod $(whoami) -aG wheel
	echo -e "* Install host app for PassFF Firefox extension..."
	curl -sSL github.com/passff/passff-host/releases/latest/download/install_host_app.sh | bash -s -- firefox
	echo -e "* Set Firefox to be the default browser, probably overwritten by Chromium..."
	xdg-settings set default-web-browser firefox.desktop
	echo -e "* Ensure keyboard will still be in AZERTY mode when plugged/unplugged..."
	# This creates a Xorg configuration file
	sudo localectl --no-convert set-x11-keymap fr
	echo -e "* Create a symlink rrm → rm (rm will be an alias to rmtrash) in zsh"
	echo -e "* Install synchronization extension for VSCode settings and plugins..."
	# Avoid to push whole extensions up to hundreds of MB, and avoid using
	# Micro$oft proprietary stuff, usable with any git server
	vscodium --install-extension zokugun.sync-settings
	git clone git@git.chosto.me:Chosto/codium-settings.git ~/.config/codium-settings
	echo -e "* Install plugin to pick theme for Terminator..."
	# See https://github.com/EliverLara/terminator-themes
	mkdir -p $HOME/.config/terminator/plugins
	wget https://git.io/v5Zww -O $HOME"/.config/terminator/plugins/terminator-themes.py"
}

# Use XDG_CONFIG_HOME if defined, default otherwise
CONFIG=${XDG_CONFIG_HOME:-$HOME/.config}

ENV=${1}

# First thing to do, before symlinks
for m in ${MERGE_DIRS}; do
	if [ -f "${CONFIG}/${m}/${MERGE_CONFIG_FOLDER}/above" ]; then
		merge_config $m ${ENV} true
	else
		merge_config $m ${ENV}
	fi
done

echo -e "\n=== Create symlink to *.${ENV} regular files ==="
# Take all specific files and create a symlink pointing to it without the extension
# This file will be used by applications
for f in `find ${CONFIG} -type f -name "*.${ENV}"`; do
	echo "${f%.*} → ${f}"
	ln -sf ${f} ${f%.*}
done
# Take care of config files at home level, outside ${CONFIG} (e.g. Xresources)
for f in `find ${HOME} -maxdepth 1 -mindepth 1 -type f -name "*.${ENV}"`; do
	echo "${f%.*} → ${f}"
	ln -sf ${f} ${f%.*}
done

echo -e "\n=== Copy changed configuration which resides in outer directory ==="
# Destination files are regular files
for f in `find ${CONFIG} -type f -name ${DEST_FILENAME}`; do
	DIR=`dirname "${f}"`
	DEST=`cat ${f}`
	# Get all files, either regular files or symlinks, which are not the destination file nor specific desktop/laptop files
	# This is because if desktop/laptop files exist, they already have a symlink pointing to them at this stage
	# We want to get the path relative to the directory we are searching in, so subfolders are kept when copying
	for config_file in `find ${DIR} -regextype posix-extended -mindepth 1 \( -type f -o -type l \) -not \( -regex "${ENV_EXT_REGEXP}" -o -name "${DEST_FILENAME}" \) -exec realpath -s --relative-to ${DIR} {} \;`; do
		# If we have to copy to a subfolder, extract it
		if echo ${config_file} | grep -q '/'; then
			subfolder=${config_file%/*}
		else
			subfolder=''
		fi
		filename=${config_file##*/}
		# Now copy to destination
		real_dest=${DEST}/${subfolder}
        sudo mkdir -p ${real_dest}
		absolute_source=`realpath "${DIR}/${config_file}"`
		check_copy "${absolute_source}" "sudo cp ${absolute_source} ${real_dest}" "sudo rm ${real_dest}/${filename}"
	done
done

if [ ! -z "$INIT" ]; then
	init_system
fi

if [ ! -z "${WM_RESTART}" ]; then
	echo -e "\n=== Restart graphical environment ==="
	# Reload i3 configuration
	i3-msg restart

	# Restart picom due to this bug https://github.com/yshui/picom/issues/166
	killall picom
	picom &>/dev/null &
fi