#!/bin/bash

WarningAbout() {
    source /etc/eos-color.conf
    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                          # time spent in fetching a file
    local -r progname=${0##*/}

    url+=/state

    time=$(curl --fail -Lsm $timeout -w "%{time_total}" "$url")              # $time contains the file fetch time and EndeavourOS update level
    curl_exitcode=$?

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

	    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 "$@"
