#!/bin/sh
#
# Copyright (C) 2012-2020, 2025  Etersoft
# Copyright (C) 2012-2020, 2025  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/>.
#

VALID_BACKENDS="apt-rpm apt-dpkg apm-rpm stplr aptitude-dpkg deepsolver-rpm urpm-rpm packagekit pkgsrc pkgng redox-pkg emerge pacman yay aura yum-rpm dnf-rpm snappy zypper-rpm mpkg eopkg conary npackd slackpkg homebrew opkg nix apk tce guix termux-pkg aptcyg xbps appget winget"

# Check if args contain backend:package syntax (snap:pkg, nix:pkg)
__has_backend_syntax()
{
    [ -z "$PPARGS" ] && echo "$*" | grep -q -E '(^| )[a-z][a-z][a-z]*:'
}

# Check if args contain repo/package syntax (p10/pkg, sisyphus/pkg)
__has_repo_syntax()
{
    [ -z "$PPARGS" ] && echo "$*" | grep -q -E '(^| )[a-zA-Z][a-zA-Z0-9]*/'
}

__get_tpmtype() {
    local arg="$1"
    local tpmtype="$(echo "$arg" | cut -d: -f1)"

    # need first three chars
    echo "$arg" | grep -q "^[a-z][a-z][a-z-]*:" || return

    # aliases
    [ "$tpmtype" = "pkcon" ] && tpmtype="packagekit"
    # use same suffix as current PMTYPE for ambiguous backends
    [ "$tpmtype" = "apt" ] && tpmtype="apt-${PMTYPE#*-}"

    echo "$VALID_BACKENDS" | tr ' ' '\n' | grep -w "^$tpmtype" | head -1
}

# TODO: get list
VALID_BRANCH="p8 p9 p10 p11 Sisyphus c10f2"

__get_repo_name() {
    local arg="$1"
    local trepo="$(echo "$arg" | cut -d/ -f1)"

    # ALT Linux branches
    [ "$trepo" = "sisyphus" ] && trepo="Sisyphus"
    [ "$trepo" = "SS" ] && trepo="Sisyphus"
    [ "$trepo" = "archive" ] && repo="archive $(echo "$arg" | cut -d/ -f2)" && name=$(echo "$arg" | cut -d/ -f3) && return

    trepo="$(echo "$VALID_BRANCH" | tr ' ' '\n' | grep -w "^$trepo")"
    [ -n "$trepo" ] && repo="$trepo" && name=$(echo "$arg" | cut -d/ -f2) && return

    # Arch Linux AUR
    if [ "$(echo "$arg" | cut -d/ -f1)" = "aur" ] && [ "$PMTYPE" = "pacman" ] ; then
        repo="aur"
        name=$(echo "$arg" | cut -d/ -f2)
    fi
}

# call: __process_backend_arguments <function> args...
__process_backend_arguments() {
    local func="$1"
    shift
    local pmtype
    local name
    local arg
    local package_groups
    declare -A package_groups
    for arg in "$@"; do
        pmtype=$PMTYPE
        name="$arg"
        case "$arg" in
            *:*)
                local tpmtype="$(__get_tpmtype "$arg")"
                if [ -n "$tpmtype" ] ; then
                    pmtype=$tpmtype
                    # copied from distr_info
                    if [ "$pmtype" = "dnf-rpm" ] && a= dnf --version | grep -qi "dnf5" ; then
                        pmtype="dnf5-rpm"
                    fi
                    name=$(echo "$arg" | cut -d: -f2)
                fi
                ;;
        esac
        package_groups["$pmtype"]+="$name "
    done

    for pmtype in "${!package_groups[@]}"; do
        (PMTYPE="$pmtype" PPARGS=1 $func ${package_groups[$pmtype]})
    done
}

# call: __process_repo_arguments <function> args...
__process_repo_arguments() {
    local func="$1"
    shift
    local repo
    local name
    local arg
    local repo_groups
    declare -A repo_groups
    for arg in "$@"; do
        repo="."
        name="$arg"
        case "$arg" in
            */*)
                __get_repo_name "$arg"
                ;;
        esac
        repo_groups["$repo"]+="$name "
    done

    for repo in "${!repo_groups[@]}"; do
        if [ "$repo" = '.' ] ; then
            (PPARGS=1 $func ${repo_groups[$repo]})
        elif [ "$repo" = 'aur' ] ; then
            # Arch Linux AUR
            (PMTYPE=aur-pacman PPARGS=1 $func ${repo_groups[$repo]})
        else
            # ALT Linux repo switching
            load_helper epm-update
            load_helper epm-reposave
            try_change_alt_repo
            docmd epm --auto repo set $repo
            __epm_update
            (PPARGS=1 $func ${repo_groups[$repo]})
            docmd epm repo restore
            end_change_alt_repo
        fi
    done
}
