#!/usr/bin/env bash

echo "/.githooks/pre-commit executing..."

# generate a random 16 characters long string that will be used
# to distinguish "user" stash entries from "pre-commit" stash entries
function gen_stash_id()
{
    abc="abcdefghijklmonpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    stash_id=""

    for i in {1..16}
    do
        stash_id+=${abc:$RANDOM % ${#abc}:1}
    done

    echo "$stash_id"
}

# there may be unstaged changes that were stashed before 'black' and other tools ran
# try to pop them from the stash
function pop_stash()
{
    # check if the top entry on the stash has the message matching the content of '.stash-id' file
    # if it matches, there were unstaged changes prior to the commit that should be popped from the stash now
    # in the other case there were no unstaged changes
    git stash list -n 1 | grep -f .stash-id >/dev/null 2>&1

    if [ $? -eq 0 ];
    then
        # this command should not case merging issues
        git stash pop >/dev/null
    fi
    rm .stash-id
}

function check_last_command()
{
    if [ $? -gt 0 ];
    then
        # something went wrong
        # revert all changes made by 'black' and the other tools
        git restore .
        pop_stash;
        exit 1;
    fi
}

export WAKE_SKIP_PREPARE_COMMIT_MSG_HOOK=1
export WAKE_SKIP_POST_COMMIT_HOOK=1

stash_id=$(gen_stash_id)
echo "$stash_id" > .stash-id

# commit staged changes so that they are not included into the stash
git commit --no-gpg-sign --no-verify -m 'pre-commit hook tmp commit' >/dev/null
commited=$?
# stash unstaged changes
git stash -u -m "$stash_id" -- . >/dev/null
# restore staged changes
if [ $commited -eq 0 ];
then
    git reset --soft 'HEAD^'
fi

unset WAKE_SKIP_PREPARE_COMMIT_MSG_HOOK
unset WAKE_SKIP_POST_COMMIT_HOOK

# find all staged "*.py" files
pyfiles=()
IFS=$'\n'
for f in $(git diff --cached --name-only --relative --diff-filter=ACMR -- wake wake_detectors wake_printers tests)
do
    if [[ "$f" == *.py ]]; then
        pyfiles+=("$f")
    fi
done

if [ -z ${WAKE_HOOKS_RUN_ALL_TESTS+dummy} ]; then
    # WAKE_HOOKS_RUN_ALL_TESTS is unset
    echo "running \`pytest tests -m \"not slow\"\`"
    pytest tests -m "not slow";
    check_last_command;
else
    # WAKE_HOOKS_RUN_ALL_TESTS is set
    echo "running \`pytest tests\`"
    pytest tests;
    check_last_command;
fi

if [ ${#pyfiles[@]} -ne 0 ]; then
    echo "running \`black ${pyfiles[@]}\`"
    black "${pyfiles[@]}";
    check_last_command;
fi


if [ ${#pyfiles[@]} -ne 0 ]; then
    echo "running \`isort ${pyfiles[@]}\`"
    isort "${pyfiles[@]}";
    check_last_command;
fi

if [ ${#pyfiles[@]} -ne 0 ]; then
    echo "running \`pyright ${pyfiles[@]}\`"
    pyright "${pyfiles[@]}";
fi

echo "running \`mkdocs build --strict\`"
mkdocs build --strict
check_last_command

echo "/.githooks/pre-commit successfully executed."
