#!/usr/bin/env bash
BOOTSTRAP_DIR=${BOOTSTRAP_DIR:-$(pwd)/bootstrap}
INPUTFILES=$(find "${BOOTSTRAP_DIR}" -type f -name 'packages*.tsv')
OUTPUTFILE=${BOOTSTRAP_DIR}/packages_testing.tsv

pkg_all=$(pacman -Qqett)

pkg_repo=$(pacman -Qqn)
pkg_aur=$(pacman -Qqm)

while getopts "nvhf:" opt; do
    case "$opt" in
    n) DRYRUN=true ;;
    v) VERBOSE=true ;;
    f) OUTPUTFILE="$OPTARG" ;;
    h | *)
        {
            printf "\nUpdate the list of installed packages.\n\nWill compare packages committed to the dotfile repository\nand those currently installed (on an Arch system, using pacman).\nUpdates the list of committed packages in repository\nand prints out the differences as a diff.\n\nOptions:\n\n\t-h\tDisplay this help.\n\t-v\tShow verbose information.\n\t-n\tPrint out changes without changing anything (dry-run).\n"
            exit 1
        }
        ;;
    esac
done

# get all existing written packages
if [ -n "$INPUTFILES" ]; then
    INPUT=$(cat $INPUTFILES | grep -v -e '^Name	Description	Source	Target' | sort)
else
    INPUT=""
fi

print_msg() {
    # shellcheck disable=2059
    [ -n "$VERBOSE" ] && printf "$@"
}

# tsv file:
# packagename, description, source, target
# toot  a toot manager  A   D

if [ -f "${OUTPUTFILE}_TEMP" ]; then
    rm "${OUTPUTFILE}_TEMP"
fi
touch "${OUTPUTFILE}_TEMP"

# create new package list
for pkg in $pkg_all; do

    source=""
    if echo "$pkg_repo" | grep -F -q -x "$pkg"; then
        source="R"
    elif echo "$pkg_aur" | grep -F -q -x "$pkg"; then
        source="A"
    else
        echo "ERROR: The package $pkg could not be found in repositories or AUR."
        exit 1
    fi

    desc=$(pacman -Qs "$pkg" | grep -A1 --color "local/$pkg\s" | tail -n1)
    #remove leading whitespace
    desc="${desc#"${desc%%[![:space:]]*}"}"

    target=""
    found_line=$(echo "$INPUT" | grep -e "^$pkg")
    if [ -n "$found_line" ]; then
        target=$(echo "$found_line" | cut -f4)
        print_msg "Updating pkg: %s:%s from: %s, for: %s\n" "$pkg" "$desc" "$source" "$target"
    else
        print_msg "Adding pkg: %s:%s from: %s, for: %s\n" "$pkg" "$desc" "$source" "$target"
    fi

    printf "%s\t%s\t%s\t%s\n" "$pkg" "$desc" "$source" "$target" >>"${OUTPUTFILE}_TEMP"
done

# notify on any removed packages
while read -r line; do
    if ! echo "$line" | cut -f1 | xargs -I _ grep -F -q -x _ <(echo "$pkg_all"); then
        printf "REMOVED: %s\n" "$line"
    fi
done <<<"<(echo $INPUT | tail +2)"

# show file changes
if [ -f "$OUTPUTFILE"_TEMP ]; then
    changes=$(diff --color=always -y --suppress-common-lines <(echo "$INPUT") <(sort "$OUTPUTFILE"_TEMP | tail -n+2))
    printf "FILE CHANGES:\n=============\n%s" "$changes"
fi

# actually write changes to file
if [ -z "$DRYRUN" ]; then

    while IFS= read -r line; do
        sed -i -e "/^${line//\//\\/}$/d" "$OUTPUTFILE"_TEMP
    done <<< "$INPUT"

    cat <(printf "Name\tDescription\tSource\tTarget\n") "${OUTPUTFILE}_TEMP" > "$OUTPUTFILE"
fi
rm "${OUTPUTFILE}_TEMP"
