#!/usr/bin/env bash

source "$(dirname "$0")/utils"

[[ "$1" == "menu" ]] && MENU=1 || MENU=0
selected=$2

returnMenu() {
    printf '\e[?25l'
    echo -e "\n$(colorize blue bold $ICO_RETURN $MNG_RETURN)"
    IFS= read -rs
    exec "$scriptDir/management" "$selected"
}

rank_mirrors() {
    while IFS= read -r line <&3; do
        [[ "$line" =~ ^[[:space:]]*#?[[:space:]]*Server[[:space:]]*=[[:space:]]*(.+) ]] || continue
        
        local server="${BASH_REMATCH[1]}"
        server="${server%%#*}"
        server="${server%"${server##*[![:space:]]}"}"

        local domain="$server"
        if [[ "$server" =~ ^([^/]+//[^/]+) ]]; then
            domain="${BASH_REMATCH[1]}"
        fi

        local url="${server%/}"
        url="${url//'$arch'/$(uname -m)}"
        url="${url//'$repo'/core}"
        url="${url}/core.db"

        local response=$(curl -s -m 9 -w "%{time_total} %{http_code}" "$url" -o /dev/null 2>/dev/null)
        local exit_code=$?
        local time status
        
        if [[ $exit_code -ne 0 ]]; then
            status="Unreachable"
        else
            time="${response%% *}"
            local code="${response##* }"
            [[ -z "$code" || $code -lt 200 || $code -gt 299 ]] && status="Unreachable"
        fi
        
        if [[ -n "$status" ]]; then
            if [ "$mirrorProgress" = true ]; then
                echo "$(colorize red bold $status)    $domain" >&2
            fi
            continue
        fi

        if [ "$mirrorProgress" = true ]; then
            echo "$(colorize gray bold "$time" sec)   $domain" >&2
        fi
        echo "$time $server" >> "$rankmirrors_time"
    done 3< "$rankmirrors_mirrorlist"

    echo "## Artix Linux repository mirrorlist" > "$rankmirrors_mirrorlist"
    echo "## Generated by Euri Apdatifier on $(date '+%Y-%m-%d %H:%M:%S')" >> "$rankmirrors_mirrorlist"

    sort -n -o "$rankmirrors_time" "$rankmirrors_time"
    local i=0
    while IFS=' ' read -r time server; do
        [[ -n "$mirrorCount" && "$mirrorCount" -gt 0 && $i -ge "$mirrorCount" ]] && break
        echo "Server = $server" >> "$rankmirrors_mirrorlist"
        ((i++))
    done < "$rankmirrors_time"
}

validate() {
    ! grep -qE '^[[:space:]]*#?[[:space:]]*Server[[:space:]]*=[[:space:]]*' "$1" && return 1
    return 0
}

mirrorfile="/etc/pacman.d/mirrorlist"
OUTDATED=false
[[ ! -f "$mirrorfile" ]] && {
    NORM_TIME="(no file)"
    OUTDATED=true
} || {
    FILE_TIME=$(date -r "$mirrorfile" +%s)
    NORM_TIME=$(date -d @"$FILE_TIME" +"%d %b %H:%M:%S")
    CURR_TIME=$(date +%s)
    [[ "$mirrors" == "age" && $MENU -eq 0 ]] && {
        (( CURR_TIME - FILE_TIME >= mirrorsAge * 86400 )) && OUTDATED=true || exit
    }
}

[[ "$mirrors" != "force" || $MENU -eq 1 ]] && {
    printImportant "$MIRROR_TIME" "$NORM_TIME"
    while true; do
        printQuestion "$MIRROR_REFRESH"; read -r answer
        case "$answer" in
            [Yy]*) echo; break;;
            [Nn]*|"") (( MENU )) && { returnMenu; } || { echo; exit; };;
            *) ;;
        esac
    done
}

rankmirrors_mirrorlist="$(mktemp)"
rankmirrors_time="$(mktemp)"

trap 'rm -f "$rankmirrors_mirrorlist" "$rankmirrors_time"' INT TERM EXIT

curl -s -m 10 -o "$rankmirrors_mirrorlist" "$dynamicUrl" 2>/dev/null & printWhile $! "$MIRRORS_FETCH"
if ! validate "$rankmirrors_mirrorlist"; then
    printError "$MIRRORS_ERR"
    printError "No server entries found."
    (( MENU )) && returnMenu || exit
fi

if [ "$mirrorProgress" = true ]; then
    echo -e "$(colorize blue bold "$ICO_MIRRORS $MIRRORS_RANK")"
    rank_mirrors
else
    rank_mirrors & printWhile $! "$MIRRORS_RANK"
fi

if ! validate "$rankmirrors_mirrorlist"; then
    (( MENU )) && returnMenu || exit
fi

${sudoBin} -n true 2>/dev/null || { echo; printImportant "$MIRRORS_SUDO"; }
cat "$rankmirrors_mirrorlist" | ${sudoBin} tee "$mirrorfile" > /dev/null

if [ $? -eq 0 ]; then
    printDone "$mirrorfile $MIRRORS_UPD"
    echo -e "$y$(tail -n +3 "$mirrorfile" | sed 's/Server = //g')$c\n"
    (( MENU )) && returnMenu
else
    printError "$MIRRORS_SUDO"
    (( MENU )) && returnMenu || exit
fi
