#!/bin/bash

# The whole script is wrapped in { ...; exit; } so bash parses all of it before
# running anything. That way, replacing this file mid-run (e.g. by git pull and
# the copy below) can't make the running copy read a mix of old and new text.
{

# Install a script atomically (copy to a temp file, then rename over the target)
install_script() {
    local tmp
    tmp="$(mktemp "$2.XXXXXX")" && cp "$1" "$tmp" && chmod 755 "$tmp" && mv -f "$tmp" "$2"
}

# Print the logo
print_logo() {
    cat << "EOF"

                                                                                                     
    ██                                                                                               
  █   ██                                                                                             
    ██    ██████    █████         ██    █████     █████     ████    ██        █████         ██       
         ██    ██  ██   ███  ███████   ██   ██   ██   ██       ██  ████████  ██    ██  ███████       
         █████     ██████   ██    ██   ██████    ██      ████████   ██   █   ███████   ██   ██       
         ██        ██████    ███████   ██████    ██       ██████    ██████   ██████    ███████       
                                                                                                     

EOF
}

# Clear screen and show logo
clear
print_logo

COREDESKTOP="$HOME/.local/share/coredesktop"

echo "Updating CoreDesktop..."
if [[ -z "$UPDATE_REEXECED" ]] && ! git -C "$COREDESKTOP" pull; then
    echo "WARNING: could not pull the latest CoreDesktop; running the update hooks already on disk."
    export UPDATE_PULL_FAILED=1
fi
mkdir -p "$COREDESKTOP/updates.d"
install_script "$COREDESKTOP/update" ~/.local/bin/update
install_script "$COREDESKTOP/refresh" ~/.local/bin/refresh
install_script "$COREDESKTOP/sibling" ~/.local/bin/sibling

if [[ -z "$UPDATE_REEXECED" ]]; then
    export UPDATE_REEXECED=1
    exec ~/.local/bin/update
fi

# Ask for the password once, then keep sudo's cached credentials fresh until
# update exits, so long-running hooks don't stop for a password again.
sudo -v || exit 1
while kill -0 $$ 2>/dev/null; do sudo -n -v; sleep 60; done 2>/dev/null &
SUDO_KEEPALIVE_PID=$!
trap 'kill "$SUDO_KEEPALIVE_PID" 2>/dev/null' EXIT

FAILED=()
[[ -n "$UPDATE_PULL_FAILED" ]] && FAILED+=("git pull")

# Each hook runs in its own subshell so a cd, set -e, exit, or stray variable
# in one hook can't leak into or abort the hooks after it.
for plugin in "$COREDESKTOP/updates.d/"*.sh; do
    [ -f "$plugin" ] || continue
    (
        unset -f is_installed run_update
        source "$plugin"
        if declare -f run_update > /dev/null; then
            if ! declare -f is_installed > /dev/null || is_installed; then
                run_update
            fi
        fi
    )
    # Checked separately: under `( ... ) ||`, bash would ignore set -e inside the hook
    [ $? -eq 0 ] || FAILED+=("$(basename "$plugin")")
done

if (( ${#FAILED[@]} > 0 )); then
    echo "Done, with errors in: ${FAILED[*]}"
    exit 1
fi

echo "Done."
exit 0
}
