#!/bin/bash

# Make commands output independent from language
LANG=en

root_check() {
    [[ $EUID != 0 ]] && err "Please run as root."
}

args_check() {
    [[ $1 -lt $2 || $1 -gt $3 ]] && err "Please use the right amount of arguments (use -h for help)."
}

err() {
    printf "\e[31mError:\e[0m $1\n" 1>&2; exit 1
}

kernel_usage() {
    echo "Usage: mhwd-kernel [option]
    -h  --help              Show this help message
    -i  --install           Install a new kernel        [kernel(s)] [optional: rmc = remove current kernel]
    -l  --list              List all available kernels
    -li --listinstalled     List installed kernels
    -lr --listrunning       List running kernel
    -r  --remove            Remove a kernel             [kernel(s)]"
}


kernel_install() {
    pkginstall=()
    rmc=0

    for kernel in "$@"; do
        [[ $kernel = "rmc" ]] && rmc=1 && continue
        [[ $current = $kernel ]] && err "You can't reinstall your current kernel. Please use 'pacman -Syu' instead to update."
        [[ -z $(pacman -Ssq "^$kernel$") ]] && err "Please make sure if the given kernel(s) exist(s).\n$(kernel_repo)"
        
        for pkg in $(pacman -Qqs "$current"); do
            pkg=${pkg//$current/$kernel}
            [[ -n $(pacman -Ssq "^$pkg$" | grep -E "^$pkg$|^$pkg-\S+$") ]] && pkginstall+=("$pkg")
        done
    done

    pacman -Syy

    outofdate="$(pacman -Qqu | tr '\n' ' ')"
    if [[ -n $outofdate ]]; then
        echo "The following packages are out of date, please update your system first: $outofdate" >&2
        read -p "Do you want to continue anyway? [y/N] " yesno
        [[ $yesno = [Yy]?([Ee][Ss]) ]] || exit 1
    fi

    pacman -Syu "${pkginstall[@]}"

    [[ $rmc = 1 && $? = 0 ]] && pacman -R $(pacman -Qqs $current)
    [[ $rmc = 1 && $? != 0 ]] && { echo ""; err "'rmc' aborted because the kernel failed to install or canceled on removal."; }
}


kernel_repo() {
    printf "\e[32mavailable kernels:\e[0m \n"
    [[ $EUID == 0 ]] && pacman -Fy > /dev/null
    pacman -Fx 'usr/lib/modules/(.*)/vmlinuz' | awk '{print $5" "$6}'
}


kernel_list() {
    printf "\e[32mCurrently running:\e[0m $(uname -r) (${current})\n"
    echo "The following kernels are installed in your system:"
    pacman -Qo /usr/lib/modules/*/modules.builtin | awk '{print "local/"$5" "$6}'
}


kernel_remove() {
    pkgremove=()

    for kernel in "$@"; do
        [[ -z "$kernel" ]] && err "Invalid argument (use -h for help)."
        [[ $current = $kernel ]] && err "You can't remove your current kernel."
        [[ -z $(pacman -Qqs "^$1$") ]] && err "Kernel not installed.\n$(kernel_list)"

        for pkg in $(pacman -Qqs "$kernel" | grep -E "^$kernel$|^$kernel-\S+$"); do
            pkgremove+=("$pkg")
        done
    done

    pacman -R "${pkgremove[@]}"
}


kernel_running() {
	grep -Po '(?<=initrd\=\\initramfs-)(.+)(?=\.img)|(?<=boot\/vmlinuz-)([^ $]+)' /proc/cmdline

}


IFS=. read -r major minor _ <<< "$(uname -r)"
current="$(kernel_running)"

case "$1" in
    -h | --help)            args_check $# 1 1
                            kernel_usage
                            exit 0;;
    -i | --install)         shift
                            root_check
                            kernel_install $@
                            exit 0 ;;
    -l | --list)            args_check $# 1 1
                            kernel_repo
                            exit 0 ;;
    -li| --listinstalled)   args_check $# 1 1
                            kernel_list
                            exit 0 ;;
    -lr| --listrunning)     args_check $# 1 1
                            kernel_running
                            exit 0 ;;                        
    -r | --remove)          shift
                            root_check
                            kernel_remove $@
                            exit 0 ;;
    -*)                     err "Invalid argument (use -h for help)." ;;
    *)                      err "No arguments given (use -h for help)." ;;
esac
