#!/bin/bash
#
# Select pacman mirrors with a simple GUI.
#

source /usr/share/endeavouros/scripts/eos-script-lib-yad || exit 1
export -f eos_yad
export -f eos_yad_terminal
export -f eos_yad_RunCmdTermBash
export -f eos_select_browser

AssignIconVariables_in_eos_bash_shared

DIE() {
    eos_yad --form --width=400 --title="reflector-simple problem" --image=$ICO_ERROR --text="$1" --button=yad-quit
    Destructor
    exit 1
}
echo2() { echo "$@" >&2; }
INFO() { echo2 "$progname: info: $1"; }
WARN() {
    echo2 "$progname: warning: $1"
    # eos_yad --form --width=400 --title="reflector-simple warning" --image=$ICO_WARNING --text="$1" --button=yad-quit
}

Verbose() {
    return
    local time=$(date +%H:%M:%S)
    echo2 "$time: $1"
}

CodeToCountry() {  # convert country code to country name
    local code="$1"
    echo "$REFLECTOR_COUNTRIES" | grep -wi "$code" | sed 's|^\(.*[a-z]\)[ ]*[A-Z][A-Z].*$|\1|'
}
CountryToCode() {  # convert country name to country code
    local country="$1"
    echo "$REFLECTOR_COUNTRIES" | grep -w "$country" | awk '{print $(NF-1)}'
}


CCCheck() {   # check validity of country code
    case "$1" in
        [A-Z][A-Z])
            if [ -n "$(CodeToCountry "$1")" ] ; then
                echo "$1"
                return 0
            fi
            ;;
    esac
    return 1  # fail
}

Method0() {
    local code="$(show-location-info country)"
    CCCheck "$code"
}
Method1() {
    # use ipv4 and 'dig' with google, then 'geoiplookup'
    Method12_IP || return 1
    local code="$(geoiplookup "$IP" | sed 's|^.*: \([A-Z][A-Z]\),.*$|\1|')"
    CCCheck "$code"
}
Method2() {
    # use ipv4 and 'dig' with google, then 'whois'
    Method12_IP || return 1
    local code="$(whois "$IP" | grep ^country: | awk '{print $NF}')"
    CCCheck "$code"
}
Method3() {
    # use ipv6 and 'dig' with google, then 'geoiplookup6'; note that ipv6 may not be available
    Method34_IP || return 1
    local code="$(geoiplookup6 "$IP" | sed 's|^.*: \([A-Z][A-Z]\),.*$|\1|')"
    CCCheck "$code"
}
Method4() {
    # use ipv6 and 'dig' with google, then 'whois'; note that ipv6 may not be available
    Method34_IP || return 1
    local code="$(whois "$IP" | grep ^country: | awk '{print $NF}')"
    CCCheck "$code"
}
Method5() {
    # net services failed, use local variables, but may be wrong
    local code="$(locale | grep ^LC_TIME | cut -d '"' -f 2 | sed 's|^.*_\([A-Z][A-Z]\)\..*$|\1|')"
    CCCheck "$code"
}

Method12_IP() {
    if [ -z "$IP_method12" ] ; then
        local xx="$(dig -4 TXT +short o-o.myaddr.l.google.com @ns1.google.com | tr -d '"')"  # ipv4 address
        if [ -n "$(echo "$xx" | sed 's|[0-9\.]*||g')" ] ; then
            return 1   # is not an ipv4 address
        fi
        IP_method12="$xx"
    fi
    IP="$IP_method12"
}

Method34_IP() {
    if [ -z "$IP_method34" ] ; then
        local xx="$(dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | tr -d '"')"  # ipv6 address (preferred)
        if [ -n "$(echo "$xx" | sed 's|[0-9a-fA-f:]*||g')" ] ; then
            return 1   # is not an ipv6 address
        fi
        IP_method34="$xx"
    fi
    IP="$IP_method34"
}

AllAreInstalled() {
    local pkg ok=yes
    for pkg in "$@" ; do
        if [ -z "${pinst[$pkg]}" ] ; then
            if expac -Q %n "$pkg" >& /dev/null ; then
                pinst[$pkg]=yes
            else
                pinst[$pkg]=no
                INFO "package $pkg is not installed"
                ok=no
            fi
        else
            [ "${pinst[$pkg]}" = "no" ] && ok=no
        fi
    done
    echo "$ok"
}

RunMethod() {
    local method="$1"
    case "${supported_methods[$method]}" in
        yes) Method$method && return 0 ;;
        *)   INFO "method $method not supported due to missing dependencies" ;;
    esac
    return 1
}

GetYourCountryCode() {
    local IP
    local IP_method12=""
    local IP_method34=""
    declare -A pinst=()
    local supported_methods=()

    AllAreInstalled bind geoip whois >/dev/null

    supported_methods=(
        yes                             # 0
        $(AllAreInstalled bind geoip)   # 1
        $(AllAreInstalled bind whois)   # 2
        $(AllAreInstalled bind geoip)   # 3
        $(AllAreInstalled bind whois)   # 4
        yes                             # 5
    )

    # try the preferred method first
    case "$REFLECTOR_SIMPLE_COUNTRY_METHOD" in
        default) ;;
        [0-5])   RunMethod $REFLECTOR_SIMPLE_COUNTRY_METHOD && return ;;
        *)       DIE "method $REFLECTOR_SIMPLE_COUNTRY_METHOD of REFLECTOR_SIMPLE_COUNTRY_METHOD in unsupported" ;;
    esac

    # come here if the preferred method failed, or default was chosen
    
    local method
    for method in $(seq 0 5) ; do
        if [ "$method" != "$REFLECTOR_SIMPLE_COUNTRY_METHOD" ] ; then
            RunMethod $method && return
        fi
    done

    WARN "failed to find country code"
}

ArgsYesNo() {
    local searched="$1"
    shift
    for xx in "$@" ; do
        test "$xx" = "$searched" && { echo "yes" ; return ; }
    done
    echo "no"
}

IsDroppedCountry() {
    local xx
    for xx in "${conf_dropped_countries[@]}" ; do
        [ "$xx" = "$1" ] && return 0
    done
    return 1
}

_config_country() {
    local xx="$1"
    case "$xx" in
        [a-zA-Z][a-zA-Z]) conf_selected_countries+=("$(CodeToCountry "$xx")") ;;
    esac
}

GetListToken() {
    local -n __lista__=$1
    local -n __token__=$2
    __token__=${__lista__%%,*}              # first token
    __lista__=${__lista__#$__token__}       # remove first token from list
    __lista__=${__lista__#,}                # remove first , from list
}

Destructor() {
    [ -n "$tmpconf" ] && rm -f $tmpconf
}

# Conf limitations:
# - nothing known!

Usage() {
    if true ; then
    cat <<EOF
Usage: $progname [options]
Options:
    Limited number of reflector options.
EOF
    else
    cat <<-EOF
        Usage: $progname [options]
        Options:
            Limited number of reflector options.
EOF
    fi
    exit $1
}

HandleOptions() {
    local opts
    local lopts="age:,country:,country-exclude:,help,latest:,number:,protocol:,sort:,threads:"
    local sopts="a:c:hl:n:p:"

    opts="$(/bin/getopt -o=$sopts --longoptions $lopts --name "$progname" -- "$@")" || Usage 1
    eval set -- "$opts"

    local list xx yy opt=""

    while true ; do
        case "$1" in
            --)                shift; break ;;
            -h | --help)       Usage 0 ;;
            -a | --age)        conf_age="$2"; shift ;;
            -c | --country)    # list or single value: "GB,FR,DE" or "GB"
                               list="$(ChangeNamesToCodes "$2")"
                               shift
                               while [ "$list" ] ; do
                                   GetListToken list yy
                                   _config_country "$yy"
                               done
                               ;;
            $country_exclude)  case "$2" in                                # extension
                                   [a-zA-Z][a-zA-Z])
                                       xx=${2^^}
                                       yy="$(CodeToCountry "$2")"
                                       # xx="$(echo "$2" | tr "[:lower:]" "[:upper:]")"
                                       [ "$yy" ] || DIE "Unrecognized country code '$xx' with option $country_exclude in file $REFLECTOR_X_CONF, see 'reflector --list-countries'"
                                       ;;
                                   [A-Z][a-z]*)
                                       xx="$(FixCountryName "$2")"
                                       yy="$(CountryToCode "$xx")"
                                       [ -n "$yy" ] || DIE "Unrecognized country name '$xx' with option $country_exclude in file $REFLECTOR_X_CONF, see 'reflector --list-countries'"
                                       ;;
                                   *)
                                       DIE "Unrecognized country '$2' with option $country_exclude in file $REFLECTOR_X_CONF, see 'reflector --list-countries'"
                                       ;;
                               esac
                               shift
                               conf_dropped_countries+=("$xx")
                               conf_dropped_countries+=("$yy")
                               ;;
            -l | --latest)     [ "$use_number_instead_of_latest" = "yes" ] || conf_number="$2"; shift ;;
            -n | --number)     [ "$use_number_instead_of_latest" = "yes" ] && conf_number="$2"; shift ;;
            -p | --protocol)   list="$2"
                               shift
                               while [ -n "$list" ] ; do
                                   GetListToken list yy
                                   conf_protocol+=("$yy")
                               done
                               ;;
            --sort)            conf_sort="$2"; shift ;;
            --threads)         threads="$2"; shift ;;
        esac
        shift
    done
}

_get_reflector_x_configs() {
    # Read reflector options from $REFLECTOR_X_CONF,
    # convert country names to country codes, and put all options
    # into file '$tmpconf'.
    local name code ix

    INFO "reading file $REFLECTOR_X_CONF"

    # Remove empty lines and comments. Remove quotes.
    cat $REFLECTOR_X_CONF | grep -v "^[ \t]*$" | sed -e 's|[ \t]*#.*||' -e '/^$/d' | tr -d "'\""  > $tmpconf

    # change country names to country codes in $tmpconf
    for ((ix=0; ix<${#countrycodes[@]}; ix++)) ; do
        name="${countrynames[$ix]}"
        code="${countrycodes[$ix]}"
        sed -i $tmpconf \
            -e "s|'$name'|$code|gI" \
            -e "s|\"$name\"|$code|gI" \
            -e "s|\([, \t]\)$name[ \t]*$|\1$code|gI" \
            -e "s|\([, \t]\)$name,|\1$code,|gI"
    done

    HandleOptions $(cat $tmpconf)

    local zz=()
    for xx in "${conf_selected_countries[@]}" ; do
        IsDroppedCountry "$xx" || zz+=("$(CodeToCountry "$xx")")
    done
    conf_selected_countries=("${zz[@]}")
}

ChangeNamesToCodes() {
    local list="$1"
    local newlist=""
    local name
    for ((ix=1; ; ix++)) ; do
        name="$(echo "$list" | cut -s -d ',' -f $ix)"
        if [ -z "$name" ] && [ -n "$list" ] ; then
            name="$list"
            list=""
        fi
        if [ -z "$name" ] && [ -z "$list" ] ; then
            break
        fi
        case "$name" in
            [a-zA-Z][a-zA-Z])
                ;;
            *)
                name="$(FixCountryName "$name")"
                name="$(CountryToCode "$name")"
                ;;
        esac
        [ $ix -eq 1 ] && newlist+="$name" || newlist+=",$name"
    done
    echo "$newlist"
}

FixCountryName() {   # simple fix to country name to be the same as in 'reflector --list-countries'
    local name="$1"

    if [ -n "$(CountryToCode "$name")" ] ; then
        echo "$name"
        return 0
    fi
    local official_name
    name=${name,,}  # make lowercase
    for official_name in "${countrynames[@]}" ; do
        if [ "$name" = "${official_name,,}" ] ; then
            echo "$official_name"
            return 0
        fi
    done
    return 1        # country name not found!
}

ToCountryName() {
    local item="$1"
    case "$item" in
        [a-zA-Z][a-zA-Z]) CodeToCountry  "$item" ;;
        *)                FixCountryName "$item" ;;
    esac
}

IsInSelectedCountries() {
    local cname="$1"
    local xx
    for xx in "${conf_selected_countries[@]}" ; do
        [ "$xx" = "$cname" ] && return 0
    done
    return 1
}

IsInAddedCountries() {
    local ccode="$1"
    local xx
    for xx in "${added_countries[@]}" ; do
        [ "$xx" = "$ccode" ] && return 0
    done
    return 1
}

OptTypeNeeded() {
    case "$local_country_code" in
        CH|DE|DK|FI|FR|HK|IE|IS|NL|NZ|SE|SG|UK|US)
            echo "plain"
            ;;
        *)
            echo "$local_country_code"
            ;;
    esac
}

IsPositiveNumber() {
    local val="$1"

    if [ "$(echo "$val" | /usr/bin/sed 's|[0-9]*||g')" = "" ] ; then
        if [ -n "$val" ] ; then
            return 0
        fi
    fi
    return 1
}

AskCountriesAndOptions() {
    local tips=(
        "Mirror ranking preferences"
        "  - select one or more <i>countries</i>"
        "  - select <i>features</i> based on your preferences"
    )
    if [ -r "$REFLECTOR_X_CONF" ] ; then
        tips+=("\nNote: configuration file <b>$REFLECTOR_X_CONF</b> options are in use.")
    else
        tips+=("\nNote: configuration file <b>$REFLECTOR_X_CONF</b> is unavailable, using $progname defaults.")
    fi
    local ix included xx tip
    local command
    local default_age=2
    local default_sort='^age!rate!country!score!delay'
    local default_number=20
    local use_saved=""

    Verbose "Creating the yad command..."

    if [ "$use_age" = "yes" ] ; then
        case "$(OptTypeNeeded)" in
            plain) ;;                         # no additional defaults
            "")         default_age=1 ;;      # country not directly supported by Arch
            [A-Z][A-Z]) default_age=8 ;;      # country may lack https mirrors
        esac
    fi

    [ -n "$conf_age" ]     && default_age="$conf_age"
    [ -n "$conf_number" ]  && default_number="$conf_number"
    [ -n "$conf_sort" ]    && default_sort="$(echo "$default_sort" | sed -e 's|\^||' -e "s|$conf_sort|^$conf_sort|")"
    

    command=(eos_yad --form --columns=$REFLECTOR_SIMPLE_COLUMNS --title="Select Arch mirrors with $progname v$VERSION_INFO")
    command+=(--scroll --width=$REFLECTOR_SIMPLE_WIDTH --height=$REFLECTOR_SIMPLE_HEIGHT)
    command+=(--use-interp)
    tip=""
    for xx in "${tips[@]}" ; do
        tip+="${xx}\n"
    done
    tip+=""
    command+=(--text="$tip")

    for ((ix=0; ix < ${#countrycodes[@]}; ix++)) ; do
        included=false
        IsInSelectedCountries "${countrynames[$ix]}" && included=true
        if [ "${countrycodes[$ix]}" = "$local_country_code" ] && (! IsDroppedCountry "$local_country_code") ; then
            included=true
        fi
        command+=(--field="${countrynames[$ix]}:chk" $included)
    done
    command+=(--separator=" ")                      # assumes all returned values lack spaces
    command+=(--image=$ICO_PREFERENCES_SYSTEM)

    #command+=(--field=":LBL" "")
    command+=(--field="<span font='italic 14'>Feature selection\:</span>:LBL" "")
    command+=(--field="Include https mirrors:chk" true)             # always suggest https
    included=false
    for xx in "${conf_protocol[@]}" ; do
        case "$xx" in
            http) included=true ; break ;;
        esac
    done
    command+=(--field="Include http mirrors:chk" $included)
    if [ "$rsync_supported" = "yes" ] ; then
	command+=(--field="Include rsync mirrors:chk" false)
    fi
    if [ "$use_age" = "yes" ] ; then
        command+=(--field="Max hours from latest mirror sync":num $default_age)    # --age
    fi
    command+=(--field="Sort by":cb "$default_sort")                                # --sort
    if [ "$use_number_instead_of_latest" = "yes" ] ; then
        command+=(--field="Max number of mirrors":num $default_number)             # --number
    else
        command+=(--field="Max number of freshest mirrors":num $default_number)    # --latest
    fi
    command+=(--field="Download timeout in seconds":num 5)                         # --download-timeout

    [ "$threads" ] && command+=(--field="Threads":num $threads)                    # --threads

    local free_params=""
    if [ -r "$free_params_file" ] ; then
        free_params="$(/usr/bin/cat "$free_params_file" | tr '\n' ' ')"
    fi
    command+=(--field="Optional reflector params" " $free_params")    # note the initial space in value !!!

    command+=(--button=" Changelog!$ICO_CHANGES!Show the changes of this program":"Changelog"
              --button=yad-cancel:1
              --button=yad-ok:0)
    Verbose "done."

    reflector_info="$("${command[@]}")"
    case "$?" in
        1) Destructor ; exit 1 ;;
    esac
    test -z "$(echo "$reflector_info" | tr -d ' ')" && exit 1      # stop if $reflector_info has no words
    if [ "$(echo "$reflector_info" | wc -l)" != "1" ] ; then
        DIE "yad output is garbage!"
    fi
    reflector_info=($(echo $reflector_info))                       # make it an array
}

Changelog() {
    $(eos_select_browser) $(eos-github2gitlab https://github.com/endeavouros-team/PKGBUILDS/commits/master/reflector-simple)
}
export -f Changelog

BuildReflectorCommand() {
    local ix xx
    local ix_ext=""
    local ac

    reflector_cmd=(reflector --verbose)

    if [ -r "$REFLECTOR_X_CONF" ] ; then
        reflector_cmd+=($(cat $tmpconf | grep -v "^$country_exclude"))
        # now we may have countries from config file
        for ac in "${conf_selected_countries[@]}" ; do
            added_countries+=("$(CountryToCode "$ac")")
        done
    fi

    # then, add countries
    for ((ix=0; ix<${#countrycodes[@]}; ix++)) ; do
        xx="${reflector_info[$ix]}"
        test "$xx" = TRUE && {
            conf_selected_countries+=("${countrynames[$ix]}")
            if [ "${countrynames[$ix]}" != "Worldwide" ] ; then
                ac="${countrycodes[$ix]}"
                if [ 1 -eq 1 ] ; then
                    IsInAddedCountries "$ac" || {
                        added_countries+=("$ac")
                        reflector_cmd+=(-c "$ac")
                    }
                else
                    reflector_cmd+=(-c "$ac")
                fi
            else
                worldwide_selected=1
            fi
        }
    done

    # finally, add feature selections
    test "${reflector_info[$((ix++))]}" = "TRUE" && { reflector_cmd+=(--protocol https) ; https_selected=1 ; }
    test "${reflector_info[$((ix++))]}" = "TRUE" && { reflector_cmd+=(--protocol http) ; http_selected=1 ; }
    test "$rsync_supported" = "yes" && {
        test "${reflector_info[$((ix++))]}" = "TRUE" && { reflector_cmd+=(--protocol rsync) ; rsync_selected=1 ; }
    }
    if [ "$use_age" = "yes" ] ; then
        reflector_cmd+=(--age "${reflector_info[$((ix++))]}")
    fi
    reflector_cmd+=(--sort $(echo "${reflector_info[$ix]}" | tr -d '|'))  # with echo incrementing ix with ++ does not work
    ((ix++))

    xx="${reflector_info[$ix]}"
    [ $xx -le 0 ] && xx=5
    export _MAX_MIRROR_LINES_TO_SHOW="$xx"

    if [ "$use_number_instead_of_latest" = "yes" ] ; then
        reflector_cmd+=(--number "$xx")
    else
        reflector_cmd+=(--latest "$xx")
    fi
    ((ix++))
    reflector_cmd+=(--download-timeout "${reflector_info[$((ix++))]}")
    [ "$threads" ] && reflector_cmd+=(--threads "${reflector_info[$((ix++))]}")

    # add optional free parameters to the command and save free params to file
    local free_pars=()
    local next=""
    while true ; do
        xx="${reflector_info[$((ix++))]}"

        [ "$xx" ] || break

        reflector_cmd+=("$xx")
        free_pars+=("$xx")

        case "$xx" in
            -c | --country)
                next="${reflector_info[$((ix++))]}"
                reflector_cmd+=("$next")
                free_pars+=("$next")
                AdjustCountries
                ;;
            -c=* | --country=*)
                next=${xx#*=}
                AdjustCountries
                ;;
            -c*)
                next=${xx:2}
                AdjustCountries
                ;;
        esac
    done
    echo "${free_pars[@]}" > "$free_params_file"
}
AdjustCountries() {  # put countries in $next to $conf_selected_countries
    local items=() item
    readarray -t items < <(echo "$next" | tr ',' '\n')
    for item in "${items[@]}" ; do
        conf_selected_countries+=("$(ToCountryName "$item")")
    done
    next=""
}

ShowMirrorlistSaved() {
    INFO "New $ml saved."
    return  # showing dialog not really needed...

    echo "New $ml saved." | \
        eos_yad --text-info --width=300 --height=100 --align=center \
                --title="Success" --button=yad-quit:0 \
                --timeout=5 --timeout-indicator=left
}

AddCountryNamesToMirrors() {
    local full_list=$(mktemp)

    Verbose "Fetching Arch mirror list..."
    eos-latest-arch-mirrorlist $full_list || {
        WARN "cannot fetch Arch mirror list."
        rm -f $full_list
        return 1
    }

    Verbose "done."

    local selected_mirrors=$(grep "^Server = " $tmpfile | awk '{print $3}')
    local sel_mir
    local cc xx
    local country_mirrors country_and_mirror
    local found
    local headers="$(grep "^#" $tmpfile)"

    printf "%s\n" "$headers" > $tmpfile

    for sel_mir in $selected_mirrors ; do
        found=0
        for cc in "${conf_selected_countries[@]}" ; do
            country_mirrors="$(sed -n '/^## '"$cc"'$/,/^$/p' $full_list | sed '1d;$d' | awk '{print $3}')"
            for xx in $country_mirrors ; do
                if [ "$sel_mir" = "$xx" ] ; then
                    found=1
                    printf "\n## $cc\nServer = $sel_mir\n" >> $tmpfile
                    break
                fi
                test "$found" = "1" && break
            done
        done
    done
    if [ "$worldwide_selected" = "1" ] ; then
        country_mirrors="$(sed -n '/^## Worldwide$/,/^$/p' $full_list | sed '1d;$d' | awk '{print $3}')"
        printf "\n## Worldwide\n" >> $tmpfile
        for xx in $country_mirrors ; do
            case "$xx" in
                "https://"*) test $https_selected -eq 1 && echo "Server = $xx" >> $tmpfile ;;
                "http://"*)  test $http_selected  -eq 1 && echo "Server = $xx" >> $tmpfile ;;
                "rsync://"*) test $rsync_selected -eq 1 && echo "Server = $xx" >> $tmpfile ;;
            esac
        done
    fi
    rm -f $full_list
}

SaveMirrorlist() {
    local opts txt
    local font="$(FindAvailableMonoFont)"

    if (! grep "^Server = [hr]" $tmpfile >/dev/null) ; then
        txt+="$progname: no mirrors found!\n\n"
        txt+="You may need to change some option values,\n"
        txt+="e.g. use bigger <i>age</i> for mirrors or add different/more countries."
        txt=$(eos_FormMonoText "$txt")
        opts=( --form --title="Error" --image=$ICO_ERROR --button=yad-quit --text="$txt")
        eos_yad "${opts[@]}"
        return 1
    fi
    AddCountryNamesToMirrors

    opts=(--text-info
          --width=750
          --height=500
          --title="New Arch mirrorlist"
          --button=yad-quit:1 --button="yad-save!!Save to $ml":0
          --filename=$tmpfile
         )
    if [ -n "$font" ] ; then
        opts+=(--fontname="$font")
    fi

    eos_yad "${opts[@]}"

    case "$?" in
        0) pkexec bash -c "cp $ml $ml.bak && cp $tmpfile $ml" && ShowMirrorlistSaved ;;
    esac
}

ReadToolConf() {
    local def_width=1000
    local def_height=750
    local def_cols=5
    local max_cols=8

    REFLECTOR_SIMPLE_WIDTH=$def_width
    REFLECTOR_SIMPLE_HEIGHT=$def_height
    REFLECTOR_SIMPLE_COLUMNS=$def_cols
    REFLECTOR_SIMPLE_COUNTRY_METHOD=default

    if [ -r $toolconf ] ; then
        INFO "reading file $toolconf"
        source $toolconf
        if ! IsPositiveNumber "$REFLECTOR_SIMPLE_WIDTH" ; then
            WARN "$toolconf: REFLECTOR_SIMPLE_WIDTH has an invalid value, using default ($def_width)"
            REFLECTOR_SIMPLE_WIDTH=$def_width
        fi
        if ! IsPositiveNumber "$REFLECTOR_SIMPLE_HEIGHT" ; then
            WARN "$toolconf: REFLECTOR_SIMPLE_HEIGHT has an invalid value, using default ($def_height)"
            REFLECTOR_SIMPLE_HEIGHT=$def_height
        fi

        if ! IsPositiveNumber "$REFLECTOR_SIMPLE_COLUMNS" ; then
            WARN "$toolconf: REFLECTOR_SIMPLE_COLUMNS has an invalid value, using default ($def_cols)"
            REFLECTOR_SIMPLE_COLUMNS=$def_cols
        fi
        if [ $REFLECTOR_SIMPLE_COLUMNS -gt $max_cols ] ; then
            WARN "setting value of REFLECTOR_SIMPLE_COLUMNS to $max_cols"
            REFLECTOR_SIMPLE_COLUMNS=$max_cols
        elif [ $REFLECTOR_SIMPLE_COLUMNS -lt $def_cols ] ; then
            WARN "setting value of REFLECTOR_SIMPLE_COLUMNS to $def_cols"
            REFLECTOR_SIMPLE_COLUMNS=$def_cols
        fi
    else
        INFO "file $toolconf not found, using defaults."
    fi
    (( REFLECTOR_SIMPLE_WIDTH+=(100*(REFLECTOR_SIMPLE_COLUMNS - def_cols)) ))
    (( REFLECTOR_SIMPLE_HEIGHT-=(60*(REFLECTOR_SIMPLE_COLUMNS - def_cols)) ))
}

Main() {
    local internal_testing=no
    case "$1" in
        --testing) internal_testing=yes ;;
    esac
    local progname=reflector-simple
    eos_assert_deps $progname yad || return 1
    local VERSION_INFO=$(expac %v $progname)
    local ARCH_SITE=https://www.archlinux.org
    local free_params_file="$HOME/.config/reflector-simple-free-params.txt"

    Verbose "Fetching country names with reflector..."
    local REFLECTOR_LIST_COUNTRIES="$(/usr/bin/reflector --list-countries 2>/dev/null | /usr/bin/sed -n '/^-----/,//'p | /usr/bin/sed '1d')"
    Verbose "done."

    if [ -z "$REFLECTOR_LIST_COUNTRIES" ] ; then
        DIE "reflector: Fetching information from $ARCH_SITE failed!"
    fi
    REFLECTOR_COUNTRIES="$(echo "Worldwide WW 0" ; echo "$REFLECTOR_LIST_COUNTRIES")"

    local REFLECTOR_SIMPLE_CONF=/etc/reflector-simple.conf
    local toolconf=/etc/reflector-simple-tool.conf
    local REFLECTOR_AUTO_CONF=/etc/reflector-auto.conf
    local REFLECTOR_X_CONF=$REFLECTOR_SIMPLE_CONF

    local REFLECTOR_SIMPLE_WIDTH
    local REFLECTOR_SIMPLE_HEIGHT
    local REFLECTOR_SIMPLE_COLUMNS
    local REFLECTOR_SIMPLE_COUNTRY_METHOD

    if [ ! -r "$REFLECTOR_X_CONF" ] ; then
        if [ -r $REFLECTOR_AUTO_CONF ] ; then
            REFLECTOR_X_CONF=$REFLECTOR_AUTO_CONF
            WARN "Config file$REFLECTOR_SIMPLE_CONF not found, using $REFLECTOR_AUTO_CONF instead."
        fi
    fi

    local rsync_supported=no   # yes or no

    local verbose=$(ArgsYesNo -v "$@")
    local showlist=$(ArgsYesNo -l "$@")

    test "$verbose" = "yes" && echo2 "Find your country ..."

    ReadToolConf

    [ $internal_testing = yes ] && REFLECTOR_SIMPLE_COUNTRY_METHOD=2

    local local_country_code="$(GetYourCountryCode)"

    if [ -n "$local_country_code" ] ; then
        CCCheck "$local_country_code" >/dev/null || DIE "internal error with country code"
    fi
    local countrynames
    local countrycodes
    local reflector_info
    local reflector_cmd=()
    local ml=/etc/pacman.d/mirrorlist
    local conf_selected_countries=()
    local conf_dropped_countries=()
    local added_countries=()           # used in removing duplicates in given countries!
    local use_age=no                   # was yes; now we use --latest, so --age is not needed
    local conf_age=""
    local conf_sort=""
    local conf_number=""
    local conf_protocol=()
    local worldwide_selected=0
    local use_number_instead_of_latest="$REFLECTOR_SIMPLE_PREFER_NUMBER"  # from exported env var
    local threads=""
    local https_selected=0
    local http_selected=0
    local rsync_selected=0
    local country_exclude="--country-exclude"          # reflector does not have this option
    local use_pulsating_indicator=no  # yes or no
    local tmpconf=""

    case "$use_number_instead_of_latest" in
        yes | no) ;;
        *) use_number_instead_of_latest=no ;;          # new default!
    esac

    # Find countries with supported mirrors.

    readarray -t countrynames < <(echo "$REFLECTOR_COUNTRIES" | sed 's|^\(.*[a-z]\)[ ]*[A-Z][A-Z].*$|\1|')
    readarray -t countrycodes < <(echo "$REFLECTOR_COUNTRIES" | awk '{print $(NF-1)}')

    if [ -r "$REFLECTOR_X_CONF" ] ; then
        tmpconf=$(mktemp)
        Verbose "Reading config file..."
        _get_reflector_x_configs
        Verbose "done."
    else
        INFO "file $REFLECTOR_X_CONF not found, using defaults."
    fi

    # Now we have info about supported countries.
    # Next, we ask user to give some countries for mirror ranking.

    AskCountriesAndOptions   # modifies $reflector_info

    # Now we know which countries to include in mirror ranking.
    # Let's create a proper reflector command.

    BuildReflectorCommand    # uses $reflector_info and modifies $reflector_cmd

    # Add the save option here!
    local tmpfile=$(mktemp)

    # Now all is ready, so just run the command.

    if [ "$use_pulsating_indicator" = "yes" ] ; then
        local lockfile="$(mktemp "$HOME"/.lck.XXXXXXXX)"
        YadProgressPulsate "$lockfile" "Ranking mirrors, please wait..." &
    fi

    local ranklog=/tmp/mirror-rating.log
    local progress_cmd=(
        eos_yad --progress --enable-log --log-on-top --log-expanded --log-height 200 --auto-close
        --width=900 --no-buttons
        --image=$ICO_MIRROR_RANK
        --title="Mirror ranking"
        --text="Rating mirrors, please wait...\nNote: rating log will be saved in file <b>$ranklog</b>."
    )

    Verbose "Starting ranking..."
    "${reflector_cmd[@]}" 2>&1 > $tmpfile | tee $ranklog | RankProgress "$_MAX_MIRROR_LINES_TO_SHOW" | "${progress_cmd[@]}"
    Verbose "done."

    if [ "$use_pulsating_indicator" = "yes" ] ; then
        #sleep 0.5
        rm -f "$lockfile"
    fi

    # Show the result and ask permission to save the mirrorlist.

    SaveMirrorlist

    # cleanup
    rm -f $tmpfile
    if [ -r "$REFLECTOR_X_CONF" ] ; then
        Destructor
    fi
}

RankProgress() {
    local max_lines="$1"
    local line=""
    local value=0
    local line_count=-2
    while read line ; do
        if [[ "$line" != *"WARNING:"* ]]; then
            ((line_count++))
        fi
        echo "#<tt>$line</tt>"
        if [ "$line_count" -ge 0 ]; then
            value=$(( line_count*100/max_lines ))
            echo "$((  value < 100 ? value : 99  ))"
        fi
    done
    echo 100
}

Main "$@"
