#!/bin/sh
# shellcheck disable=SC3043,SC2086
# Copyright (C) 2024-2025  Etersoft
# Copyright (C) 2024  Ivan Mazhukin <vanomj@etersoft.ru>
# Copyright (C) 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/>.

load_helper epm-query


# args: de [options]
run_script()
{
    local script="$CONFIGDIR/desktop.d/$1.sh"
    [ -s "$script" ] || return
    [ -f "$script.rpmnew" ] && warning 'There is .rpmnew file(s) in $psdir dir. The desktop script can be outdated.'

    shift
    [ "$PROGDIR" = "/usr/bin" ] && SCPATH="$PATH" || SCPATH="$PROGDIR:$PATH"
    ( unset EPMCURDIR ; export PATH=$SCPATH ; $script "$@" ) || warning "Postinstall/postuninstall script for $de_name encountered an issue."
    return
}

# args: de
get_json()
{
    local de_name="$1"
    realpath $CONFIGDIR/desktop.d/$de_name.json
}

# args: de
check_if_de_exists()
{
    local de_name="$1"

    [ -n "$de_name" ] || fatal "Missed DE name."

    local json="$(get_json $de_name)"

    [ -s "$json" ] && return

    fatal 'Error: Manifest for $de_name is not found.'
}


# args: de key
get_value()
{
    local de_name="$1"
    local key="$2"

    get_json_value "$(get_json $de_name)" "$key"
}


# args: de key
get_values()
{
    local de_name="$1"
    local key="$2"

    get_json_values "$(get_json $de_name)" "$key" | xargs
}


# arg: pkgname
__get_api_url()
{
    local package_name="$1"
    local branch="$(echo "$DISTRVERSION" | tr '[:upper:]' '[:lower:]')"
    echo "https://rdb.altlinux.org/api/package/package_info?name=$package_name&arch=$DISTRARCH&source=false&branch=$branch&full=false"
}

# de
get_main_package()
{
    local de_name="$1"
    # check by the first package in the dependencies list
    local package="$(get_values "$de_name" "dependencies" | cut -d' ' -f1)"
    [ -n "$package" ] || fatal 'Cannot get package name for $de_name'
    echo "$package"
}

get_repo_version()
{
    local de_name=$1

    local package=$(get_main_package "$de_name")

    local latest_version="$(get_json_value "$(__get_api_url $package)" '["packages",0,"version"]')"

    if [ -n "$latest_version" ] ; then
        echo "$latest_version"
        return
    fi

    warning '$package package is missed in the repo, use version from the local metadata'

    epm print version for package "$package" 2>/dev/null && return

    # fallback
    get_value "$de_name" "version"
}


# args: de
is_de_installed()
{
    local de_name="$1"

    is_installed $(get_main_package $de_name)
}


install_de_meta()
{
    local metapackages="$(get_values "$de_name" "metapackages")"

    # silent skip missed metapackages
    [ -n "$metapackages" ] || return 0

    # we really want mark all installed packages as manually installed?
    epm install --manual-requires $metapackages
}


install_de()
{
    local de_name="$1"

    if [ -z "$force" ] && is_de_installed $de_name ; then
        message "$de_name is already installed."
        return 1
    fi

    local dependencies="$(get_values "$de_name" "dependencies")"

    message "Installing $de_name with dependencies: $dependencies"

    if ! install_de_meta ; then
        fatal "Failed to install metapackage(s) for $de_name."
    fi

    if ! epm install $dependencies ; then
        fatal "Failed to install $de_name."
    fi

    run_script "$de_name-postin" $de_name
    message "$de_name successfully installed."

}


remove_de()
{
    local de_name="$1"

    if [ -z "$force" ] && ! is_de_installed "$de_name" ; then
        message "$de_name is not installed."
        return 0
    fi

    local dependencies="$(get_values "$de_name" "dependencies")"

    message "Removing $de_name with dependencies: $dependencies"

    # We hope that metapackages will removed by dependency
    if ! epm remove $dependencies ; then
        fatal "Failed to remove $de_name."
    fi

    run_script "$de_name-postun" $de_name
    message "$de_name successfully removed."
}


get_de_info()
{
    local de_name="$1"
    local json_flag="$2"

    info "Trying get info from remote ALT DB ..."
    version="$(get_repo_version $de_name)"
    installed="$(is_de_installed $de_name && echo 'true' || echo 'false')"

    if [ -n "$json_flag" ]; then
        local json="$(get_json $de_name)"

        cat "$json" | sed -E 's/"version":.*"/"version": "'$version'"/g' | sed 's/"installed":.*/"installed": '$installed'/g'
        return
    fi

    message "Information for $de_name:
    Name: $(get_value $de_name name)
    Version: $version
    Installed: $installed
    Description: $(get_value $de_name description)"
}


list_des()
{
    local json_flag="$1"
    if [ -z "$json_flag" ]; then
        for de in $CONFIGDIR/desktop.d/*.json ; do
            basename "$de" .json || fatal
        done
        return
    fi

    echo '['
    local first=1
    for de in $CONFIGDIR/desktop.d/*.json ; do
        if [ $first = 1 ] ; then
            first=0
        else
            echo ','
        fi

        de_name="$(basename $de .json)" || fatal
        get_de_info "$de_name" "$json_flag"

    done
    echo ']'
}


list_installed_des()
{
    local de de_name
    for de in $CONFIGDIR/desktop.d/*.json ; do
        de_name="$(basename "$de" .json)" || fatal
        is_de_installed "$de_name" && echo "$de_name"
    done
}

epm_desktop_help()
{
    message 'Usage: epm desktop <command> [--json] [option]'
            get_help HELPCMD $SHAREDIR/epm-desktop
    message '
Examples:
  epm desktop install kde
'
}


epm_desktop()
{

    local cmd="$1"
    shift

    local json_flag=''

    case "$1" in
        --json)
            json_flag=1
            shift
            ;;
    esac

    case "$cmd" in
        "-h"|"--help"|"help")         # HELPCMD: help
            epm_desktop_help
            return
            ;;
        install)                      # HELPCMD: <de_name>   Install a desktop environment
            check_if_de_exists "$1"
            install_de "$1"
            ;;
        remove)                       # HELPCMD: <de_name>   Remove a desktop environment
            check_if_de_exists "$1"
            remove_de "$1"
            ;;
        info)                         # HELPCMD: <de_name>   Get information about a desktop environment
            check_if_de_exists "$1"
            get_de_info "$1" $json_flag
            ;;
        list)                         # HELPCMD:             List all available desktop environments
            list_des $json_flag
            ;;
        list-installed)               # HELPCMD:             List installed desktop environments
            list_installed_des
            ;;
        installed)
            is_de_installed "$1"
            ;;
        version)
            get_repo_version "$1"
            ;;
        *)
            fatal 'Unknown option $cmd. Run with --help to get help'
            ;;
    esac
}
