#!/bin/bash

#
# Default variables
#
UPGRADE_PACKAGES=false
SCRIPT_NAME="$(basename -- "$0")"
SCRIPT_DIR="$(
    cd -- "$(dirname "$0")" >/dev/null 2>&1 || exit 1
    pwd -P
)"

function _acpib() {
    acpi -b | grep -Fv ' 0%'
}

function is_laptop() {
    [[ $(_acpib | wc -l) -gt 0 ]] && return 0 || return 1
}

function usage() {
    echo "Usage: $SCRIPT_NAME [OPTIONS]"
    echo
    echo "Options:"
    echo "  -h      Display help."
    echo "  -u      Upgrade existing packages."
    exit 0
}

while getopts ":uh" arg; do
    case $arg in
    h) usage ;;
    u) UPGRADE_PACKAGES=true ;;
    :)
        echo "$0: Must supply an argument to -$OPTARG." >&2
        exit 1
        ;;
    ?)
        echo "Invalid option: -${OPTARG}."
        echo
        usage
        exit 2
        ;;
    esac
done

# Returns a comma-separated list of packages for one or more targets.
# The packages file may contain multiple rows with the same target name.
function get_packages() {
    local packages pkg_file="$SCRIPT_DIR/.installer/packages"

    for target in "$@"; do
        while read -r row; do
            for package in ${row//,/ }; do
                echo "$package"
            done
        done <<<"$(grep "^${target:?}:" "$pkg_file" | cut -d':' -f2)"
    done
}

function prepare_arch() {
    which pamac >/dev/null && return 0
    sudo pacman -S pamac --noconfirm || return 1
}

function setup_arch_with_pamac() {
    local targets=("pacman-any") packages
    is_laptop && targets+=("pacman-laptop")

    packages="$(get_packages "${targets[@]}")"
    # shellcheck disable=SC2086
    sudo pamac install $packages --no-confirm || return 1
}

function setup_arch_with_yay() {
    local targets=("aur-any") packages
    is_laptop && targets+=("aur-laptop")

    for package in $(get_packages "${targets[@]}"); do
        if pacman -Qs "^$package$" >/dev/null; then
            if $UPGRADE_PACKAGES; then
                echo "Package '$package' will be upgraded."
            else
                echo "Package '$package' already exists."
                continue
            fi
        else
            echo "Package '$package' will be installed."
        fi

        sudo pamac build "$package" --no-confirm || return 1
    done
}

function install_sddm_aerial_theme() {
    local theme_dir="/usr/share/sddm/themes/aerial"

    [ -d "$theme_dir" ] && return

    echo "Installing SDDM Aerial theme."

    git clone https://github.com/3ximus/aerial-sddm-theme.git /tmp/aerial
    sudo mv /tmp/aerial "$theme_dir"
    sudo chown -R root:root "$theme_dir"
}

function configure_sddm() {
    local sddm_config_dir="/etc/sddm.conf.d"
    local theme_dir="/usr/share/sddm/themes/aerial"
    local theme_user_config="$theme_dir/theme.conf.user"

    echo "Setting up '$sddm_config_dir'."

    if ! [ -d "$sddm_config_dir" ]; then
        sudo mkdir "$sddm_config_dir"
        sudo chown root:root -R "$sddm_config_dir"
    fi

    {
        echo "[Theme]"
        echo "Current=aerial"
    } | sudo tee "$sddm_config_dir/theme" >/dev/null

    {
        echo "[X11]"
        echo "DisplayCommand=/usr/share/sddm/scripts/Xsetup"
    } | sudo tee "$sddm_config_dir/xsetup" >/dev/null

    echo "Setting up '$theme_dir'."
    [ -f "$theme_user_config" ] && sudo mv "$theme_user_config" "$theme_user_config.disabled"
}

function configure_ufw() {
    echo "Setting up UFW."

    sudo systemctl enable ufw.service || return 1
    sudo systemctl start ufw.service || return 2
    sudo ufw enable || return 3
    sudo ufw allow ssh || return 4
}

function setup_arch() {
    prepare_arch || return 1
    setup_arch_with_pamac || return 2
    setup_arch_with_yay || return 3
    configure_sddm || return 4
    configure_ufw || return 5
}

function setup_debian_repo_i3gaps() {
    echo "Setting up repository for i3-gaps."
    sudo add-apt-repository -y ppa:regolith-linux/release
}

function setup_debian_repo_vscodium() {
    echo "Setting up repository for VSCodium."
    wget -qO - https://gitlab.com/paulcarroty/vscodium-deb-rpm-repo/raw/master/pub.gpg |
        gpg --dearmor |
        sudo dd of=/usr/share/keyrings/vscodium-archive-keyring.gpg
    echo 'deb [ signed-by=/usr/share/keyrings/vscodium-archive-keyring.gpg ] https://download.vscodium.com/debs vscodium main' |
        sudo tee /etc/apt/sources.list.d/vscodium.list
}

function prepare_debian() {
    setup_debian_repo_i3gaps || return 1
    setup_debian_repo_vscodium || return 2
}

function setup_debian_with_apt() {
    local targets=("apt-any") packages
    is_laptop && targets+=("apt-laptop")

    packages="$(get_packages "${targets[@]}")"
    sudo apt-get update
    # shellcheck disable=SC2086
    sudo apt-get install $packages -y || return 1
}

function setup_debian_with_pip(){
    local targets=("pip-any") packages

    packages="$(get_packages "${targets[@]}")"
    # shellcheck disable=SC2086
    sudo pip3 install $packages --no-input || return 1
}

function install_picom() {
    local tmp=/tmp/picom

    echo "Installing Picom."

    rm -Rf "$tmp"
    git clone https://github.com/yshui/picom.git "$tmp" || return 1
    cd "$tmp" || return 2
    git submodule update --init --recursive || return 3
    meson --buildtype=release . build || return 4
    ninja -C build || return 5
    sudo ninja -C build install || return 6
    cd || return 7
    rm -Rf "$tmp"
}

function setup_debian_with_git() {
    install_picom || return 1
    install_sddm_aerial_theme || return 2
}

function setup_debian() {
    prepare_debian || return 1
    setup_debian_with_apt || return 2
    setup_debian_with_pip || return 3
    setup_debian_with_git || return 4
    configure_sddm || return 5
    configure_ufw || return 6
}

ID_LIKE="$(grep ID_LIKE= </etc/os-release | cut -d= -f2)"

echo "Setting up ${ID_LIKE^:?}-like OS."

if [[ "$ID_LIKE" == "arch" ]]; then
    setup_arch
elif [[ "$ID_LIKE" == "debian" ]]; then
    setup_debian
else
    echo "ERROR: Unsupported system: ID_LIKE=$ID_LIKE"
    exit 2
fi

echo "Setup finished."
