#!/usr/bin/sh
#
# Copyright (C) 2015-2016, 2020, 2021  Etersoft
# Copyright (C) 2015-2016, 2020, 2021  Vitaly Lipatov <lav@etersoft.ru>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

load_helper epm-sh-altlinux
load_helper epm-repomirrors

# Convert mirror URL to sed pattern for matching (captures separator)
# https://download.etersoft.ru/pub/ALTLinux -> //download.etersoft.ru/pub\([/ ]\)ALTLinux
__url_to_sed_pattern()
{
    echo "$1" | sed -e 's|^https:||' -e 's|/\([^/]*\)$|\\([/ ]\\)\1|'
}

# Substitute known mirror URL with new one
# Uses mirror database from epm-repomirrors
__subst_with_repo_url()
{
    __load_alt_mirror_db
    local input="$1"
    local new_pattern="$2"

    local name url pattern
    while read -r name url ; do
        [ -z "$name" ] && continue
        pattern=$(__url_to_sed_pattern "$url")
        input=$(echo "$input" | sed -e "s|$pattern|$new_pattern|")
    done <<EOF
$__ALT_MIRROR_DB
EOF
    echo "$input"
}


# Replace apt sources.list lines from stdin with lines for the new mirror
__change_repo_lines()
{
    local REPLTO="$1"
    local NN
    grep -v "file:/" | while read nn ; do
        NN="$(__subst_with_repo_url "$nn" "$REPLTO")"
        [ "$NN" = "$nn" ] && continue
        epm addrepo "$NN" && epm removerepo "$nn" || return 1
    done
}

# Replace mirror in baseurl of /etc/yum.repos.d/*.repo (dnf on ALT)
__change_repo_dnf()
{
    local REPLTO="$1"
    local type url newurl

    # rpm-md metadata is not available on all mirrors: check before changing anything
    __get_alt_dnf_repos | while read -r type url ; do
        [ "$type" = "rpm-md" ] || continue
        newurl="$(__subst_with_repo_url "$url" "$REPLTO")"
        [ "$newurl" = "$url" ] && continue
        eget --check-url "$newurl/repodata/repomd.xml" && continue
        warning 'There is no rpm-md metadata at $newurl'
        return 1
    done || return

    local f line newline tmpfile
    for f in "$(__get_yum_repos_dir)"/*.repo ; do
        [ -r "$f" ] || continue
        grep -q "^[[:space:]]*baseurl[[:space:]]*=" "$f" || continue
        tmpfile=$(mktemp) || fatal
        remove_on_exit $tmpfile
        while IFS= read -r line ; do
            case "$line" in
                baseurl*|[[:space:]]*baseurl*)
                    newline="$(__subst_with_repo_url "$line" "$REPLTO")"
                    ;;
                *)
                    newline="$line"
                    ;;
            esac
            printf "%s\n" "$newline"
        done < "$f" > $tmpfile
        cmp -s "$f" $tmpfile && continue
        chmod 644 $tmpfile
        sudocmd cp $tmpfile "$f" || return
    done
}

__change_repo()
{
    local REPLTO="$1"
    case $PMTYPE in
        dnf-rpm|dnf5-rpm)
            __change_repo_dnf "$REPLTO" || return
            # dnf5 takes repos from sources.list (libdnf5-plugin-apt)
            __alt_dnf_uses_apt_sources || return 0
            load_helper epm-repolist
            ( quiet=1 ; print_apt_sources_list ) | __change_repo_lines "$REPLTO"
            ;;
        *)
            epm --quiet repo list | __change_repo_lines "$REPLTO"
            ;;
    esac
}


__epm_repochange_alt()
{
    local current_mirror mirror
    current_mirror=$(__get_current_mirror)
    mirror="$1"

    case "$mirror" in
        "--list")
            __list_mirrors "$current_mirror" "$short"
            ;;
        *)
            local pattern
            pattern="$(__alt_mirror_change_pattern "$mirror")"
            if [ -n "$pattern" ] ; then
                __change_repo "$pattern"
            else
                fatal 'Unsupported mirror: $mirror. Use --list to see available mirrors.'
            fi
            ;;
    esac
}


epm_repochange()
{
    [ "$1" = "--help" ] && message "Use --list to get all possible targets" && return
    if [ "$1" != "--list" ] ; then
        load_helper epm-repofix
        epm_repofix
    fi
    case $BASEDISTRNAME in
        "alt")
            __epm_repochange_alt "$@"
            ;;
         *)
            fatal 'Repo change Unsupported for $BASEDISTRNAME'
            ;;
    esac
}
