#!/bin/bash

WarningAbout() {
    eos-color warning 2
    printf "==> Warning about %s (curl code %s):\n" "$mirror" "$curl_exitcode" >&2
    [ "$1" ] && printf "    %s\n" "$@" >&2
    eos-color reset 2
}

RankOneMirror() {
    local url="$1"                      # mirror url without /state or /$repo/$arch
    local timeout="$2"                  # timeout for fetching a file from the mirror
    local mirror_verbosity="$3"
    local reference_level="$4"          # if empty then caller must be is fetching the reference_level !
    local mirror="$url/\$repo/\$arch"   # mirror url with /$repo/$arch
    local curl_exitcode
    local time_level                    # will contain the file fetch time and EndeavourOS update level

    url+=/state

    time_level=$(curl --fail -Lsm "$timeout" -w "%{time_total}" "$url")
    curl_exitcode=$?

    case "$curl_exitcode" in
        0)
            local update_level
            update_level=$(echo "$time_level" | head -n1)              # update level number (=state)
            time=$(        echo "$time_level" | tail -n1)              # file fetch time

	    if [ "${update_level//[0-9]/}" ] ; then   # check that $update_level is a number
		WarningAbout "Unrecognized data returned by this mirror."
                return 1
	    fi
	    if [ "${time//[0-9\.]/}" ] ; then   # check that $time is a decimal number
		WarningAbout "Unrecognized data returned by this mirror."
                return 1
	    fi

            if [ "$reference_level" ] ; then
                # ad hoc tests for the update level value in the state file
                if [ "$update_level" -ne "$reference_level" ] ; then
                    local low_limit=$((reference_level - 2))                 # still acceptable value
                    local too_low_limit=$((reference_level - 10))            # probably fails when below this
                    if [ "$update_level" -gt "$reference_level" ] ; then
                        if [ "$mirror" != "https://mirror.alpix.eu/endeavouros/repo/\$repo/\$arch" ] || [ "$update_level" -gt $((reference_level + 1)) ] ; then
                            WarningAbout "Update level $update_level is too high (> $reference_level), ignoring this mirror."
                        fi
                        return 1
                    elif [ "$update_level" -lt $too_low_limit ] ; then
                        WarningAbout "Update level $update_level/$reference_level is very low, ignoring this mirror."
                        return 1
                    elif [ "$update_level" -lt $low_limit ] ; then
                        WarningAbout "update level $update_level/$reference_level is lower than expected, will lower the ranking of this mirror."
                    fi
                fi
            fi
            echo "$mirror $update_level $time"
            ;;
        *)
            local curl_msg=""
            local msg=()
            local add_code=no
            case "$mirror_verbosity" in
                all | code | show)
                    case "$curl_exitcode" in
                        28) msg+=("Mirror timed out after $timeout seconds.") ;;
                        7)  msg+=("Failed to connect, the mirror may be currently offline.") ;;
                        *)  msg+=("Could not fetch the test file.") ;;
                    esac
                    case "$mirror_verbosity" in
                        all)
                            curl_msg="$(curl-exit-code-to-string $curl_exitcode)"
                            if [ "$curl_msg" ] ; then
                                msg+=("--> (curl exit code $curl_exitcode: $curl_msg)")
                            else
                                add_code=yes
                            fi
                            ;;
                        code)
                            add_code=yes
                            ;;
                    esac
                    [ "$add_code" = "yes" ] && msg+=("--> (curl exit code $curl_exitcode.)")

                    WarningAbout "${msg[@]}"
                    ;;
                none)
                    ;;
            esac
            return $curl_exitcode
            ;;
    esac
}

RankOneMirror "$@"
