#!/usr/bin/env bash

trap "git restore ." EXIT

GIT_AUTHOR="${AUTHOR_EMAIL:-go.wigust@gmail.com}"

patch_guix_upstream()
{
    if [[ $(git diff guix/upstream.scm) == "" ]]
    then
        patch --strip=1 <<'EOF'
diff --git a/guix/upstream.scm b/guix/upstream.scm
index 6584d5e4c4..ea94184961 100644
--- a/guix/upstream.scm
+++ b/guix/upstream.scm
@@ -24,6 +24,7 @@
   #:use-module (guix discovery)
   #:use-module ((guix download)
                 #:select (download-to-store url-fetch))
+  #:use-module (guix git-download)
   #:use-module (guix gnupg)
   #:use-module (guix packages)
   #:use-module (guix diagnostics)
@@ -400,7 +401,8 @@ SOURCE, an <upstream-source>."
 
 (define %method-updates
   ;; Mapping of origin methods to source update procedures.
-  `((,url-fetch . ,package-update/url-fetch)))
+  `((,url-fetch . ,package-update/url-fetch)
+    (,git-fetch . ,package-update/url-fetch)))
 
 (define* (package-update store package updaters
                          #:key (key-download 'interactive))
EOF
    fi
}

maintainer()
{
    mapfile -t output < <(git log --grep="gnu: Add" --format=%s --author="$GIT_AUTHOR")
    for line in "${output[@]}"
    do
        package="${line/gnu: Add /}"
        package="${package::-1}"
        case "$package" in
            *Revert*|*service*|premake4|perl-strictures-2|perl-role-tiny-2|emacs-cl-generic|emacs-seq|emacs-emms-player-simple-mpv|php-with-bcmath|shlomif-cmake-modules|go-github-com-muesli-reflow|go-github-com-emirpasic-gods-trees-binaryheap|nginx-socket-cloexec|emacs-kotlin-mode|emacs-dired-hacks|emacs-which-key)
                printf ""
                ;;
            *go-github-com*)
                printf ""
                ;;
            *zabbix-agentd*)
                printf "zabbix-agentd\nzabbix-server\n"
                ;;
            *)
                echo "$package"
                ;;
        esac
    done
}

log_packages_for_upgrade()
{
    # shellcheck disable=SC2046
    if ! [ -e refresh.log ]
    then
        printf "No refresh.log exists, creating...\n"
        ./pre-inst-env guix refresh $(maintainer) |& tee refresh.log
    fi
}

upgrade_package()
{
    printf 'Updating "%s" package and remember version.\n' "$package"
    version="$(./pre-inst-env guix refresh --update "$package" |& awk '/updating from version/ { print $NF }' | sed 's/\.\.\.//')"
    if [ -z "$version" ]
    then
        printf "No version found.\n"
        exit 1
    fi

    file="$(git diff --stat | awk '/packages/ { print $1 }')"
    printf 'Trying to build "%s" package.\n' "$package"
    mapfile -t hashes < <(./pre-inst-env guix build "$package" |& awk '/hash:/ { print $NF }')
    if [ "${#hashes[@]}" -ne 0 ]
    then
        if grep --quiet "${hashes[0]}" "$file"
        then
            if git diff "$file" | grep --quiet '(version' 
            then
                printf 'Substitute "%s" with "%s" in "%s".\n' "${hashes[0]}" "${hashes[1]}" "$file"
                if sed --in-place "s/${hashes[0]}/${hashes[1]}/" "$file"
                then
                    printf "Building package again..."
                    if ./pre-inst-env guix build "$package"
                    then
                        sed --in-place "/$package/d" refresh.log
                    fi
                fi
            else
                git restore "$file"
                printf '\033[31merror: Failed to update "%s" package. Restoring "%s" file.\033[0m\n' "$package" "$file"
                exit 1
            fi
        fi
    fi
    if [[ $(git diff "$file") == "" ]]
    then
        printf '\033[31merror: Nothing to commit.\033[0m\n'
        exit 1
    else
        if ./pre-inst-env guix build "$package"
        then
            git commit --message="$(printf "gnu: %s: Update to $version.\n\n* %s (%s): Update to $version." "$package" "$file" "$package")" "$file"
            printf '\033[32mCommit the change in "%s" file.\033[0m\n' "$file"
            git show
            sed --in-place "/$package/d" refresh.log
        else
            git restore "$file"
            printf '\033[31merror: Failed to build "%s" package. Restoring "%s" file.\033[0m\n' "$package" "$file"
        fi
    fi
}

main()
{
    case "$1" in
        debug)
            maintainer
            ;;
        *)
            patch_guix_upstream
            # XXX: Don't call .direnv/aliases/environment -- .direnv/aliases/build
            .direnv/aliases/environment -- .direnv/aliases/build
            log_packages_for_upgrade
            case "$2" in
                -i|--interactive)
                    select package in $(awk '/would be upgraded/ { print $2 }' refresh.log)
                    do
                        upgrade_package "$package"
                    done
                    ;;
                *)
                    while IFS= read -r package
                    do
                        upgrade_package "$package"
                    done < <(awk '/would be upgraded/ { print $2 }' refresh.log)
                    ;;
            esac
            ;;
    esac
}

main "$@"
