#!/usr/bin/env bash
#
system=$1
shift
IF_VERBOSE=:
SUDO=
PROMPT=
SPKG=no
INDENT=
if [ -n "$OUTPUT_RST" ]; then
    COMMENT=""
else
    COMMENT="# "
fi
while :
do
    case "$1" in
        --spkg)
            # Whether given package names are SPKG names instead of system package names
            SPKG=yes
            ;;
        --format=plain)
            unset OUTPUT_RST
            COMMENT="# "
            ;;
        --format=rst)
            OUTPUT_RST=1
            COMMENT=""
            ;;
        --verbose=*)
            IF_VERBOSE=
            COMMENT="${1#--verbose=}"
            ;;
        --verbose)
            IF_VERBOSE=
            ;;
        --sudo)
            # Whether to print sudo for package managers that need sudo for non-root users
            SUDO="sudo "
            ;;
        --indent=*)
            INDENT="${1#--indent=}"
            ;;
        --prompt=*)
            PROMPT="${1#--prompt=}"
            ;;
        --prompt)
            PROMPT='  $ '
            CONTINUATION='        '
            ;;
        --continuation=*)
            CONTINUATION="${1#--continuation=}"
            ;;
        --wrap)
            WRAP=78
            ;;
        --wrap=*)
            WRAP="${1#--wrap=}"
            ;;
        --no-install-recommends)
            NO_INSTALL_RECOMMENDS=yes
            ;;
        --yes)
            YES=yes
            ;;
        --ignore-missing)
            IGNORE_MISSING=yes
            ;;
        -*)
            echo >&2 "$0: unknown option $1"
            exit 1
            ;;
        *)
            break
    esac
    shift
done
command=$1
shift
COMMENT="${INDENT}${COMMENT}"
PROMPT="${INDENT}${PROMPT}"
CONTINUATION="${INDENT}${CONTINUATION}"
if [ -z "$system" -o -z "$command" ]; then
    echo >&2 "usage: $0 {auto|debian|arch|conda|...} [--verbose] [--sudo] [--prompt] {update|install|setup-build-env|remove|...} PACKAGES..."
    exit 1
fi
if [ "$system" = auto ]; then
    system=$(sage-guess-package-system 2>/dev/null)
    if [ "$system" = unknown ]; then
        echo >&2 "unknown package system"
        exit 1
    fi
fi
if [ "$SPKG" = "yes" -a "$system" != "spkg" ]; then
    system_packages=$(echo $(sage-get-system-packages $system $*))
else
    system_packages="$*"
fi
options=
env=
shopt -s extglob

function print_shell_command()
{
    if [ -n "$OUTPUT_RST" ]; then
        echo
        echo "${INDENT}.. CODE-BLOCK:: bash"
        echo
    fi
    # shell-quote arguments if necessary
    quoted=$(for a in "$@"; do printf "%q " $a; done)
    if [ -z "$WRAP" -o $# -lt 6 ]; then
        echo "${PROMPT}${quoted}"
    else
        sage-bootstrap-python -c "import textwrap; print(' \\\\\n'.join(textwrap.wrap(r'''${quoted}''', $WRAP, initial_indent=r'''${PROMPT}''', subsequent_indent=r'''${CONTINUATION}''', break_long_words=False, break_on_hyphens=False)))"
    fi
    if [ -n "$OUTPUT_RST" ]; then
        echo
    fi
}

function print_comment()
{
    if [ -n "$OUTPUT_RST" ]; then
        echo
    fi
    echo "${COMMENT}$1"
}

case $system:$command in
    homebrew*:setup-build-env)
        $IF_VERBOSE echo "${COMMENT}"
        $IF_VERBOSE echo "${COMMENT}Homebrew can issue suggestions regarding keg-only packages."
        $IF_VERBOSE echo "${COMMENT}The following command is to automatically apply these suggestions"
        $IF_VERBOSE echo "${COMMENT}for packages relevant for Sage to make them available for the build."
        $IF_VERBOSE echo "${COMMENT}Run it once to apply the suggestions for the current session."
        $IF_VERBOSE echo "${COMMENT}Add it to your shell profile to apply them for all future sessions."
        $IF_VERBOSE echo "${COMMENT}"
        [ -n "$SAGE_ROOT" ] || SAGE_ROOT=.
        echo "${PROMPT}source $SAGE_ROOT/.homebrew-build-env"
        ;;
    macports*:setup-build-env)
        $IF_VERBOSE echo "${COMMENT}"
        $IF_VERBOSE echo "${COMMENT}WARNING: Use of MacPorts is experimental"
        $IF_VERBOSE echo "${COMMENT}"
        $IF_VERBOSE echo "${COMMENT}MacPorts does not provide unversioned gfortran executables by default"
        $IF_VERBOSE echo "${COMMENT}To make gfortran available (and build with gcc from XCode), use:"
        $IF_VERBOSE echo "${COMMENT}"
        $IF_VERBOSE print_shell_command ./configure FC=gfortran-mp-11
        ;;
    *:setup-build-env)
        # Nothing needed
        ;;
    #
    # Verbs handled above are our own inventions. Verbs handled below are apt-get verbs.
    #
    @(debian*|ubuntu*):update)
        print_shell_command ${SUDO}apt-get $command $system_packages
        ;;
    @(debian*|ubuntu*):*)
        [ "$NO_INSTALL_RECOMMENDS" = yes ] && options="$options --no-install-recommends"
        [ "$YES" = yes ] && options="$options --yes" env="DEBIAN_FRONTEND=noninteractive "
        if [ "$IGNORE_MISSING" = yes ]; then
            [ -n "$system_packages" ] && echo "for pkg in $system_packages; do ${SUDO}${env}apt-get $command $options \$pkg || true; done"
        else
            [ -n "$system_packages" ] && print_shell_command ${SUDO}${env}apt-get $command $options $system_packages
        fi
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    @(fedora*|redhat*|centos*):install)
        [ "$YES" = yes ] && options="$options -y"
        [ "$IGNORE_MISSING" = yes ] && options="$options --skip-unavailable"
        [ -n "$system_packages" ] && print_shell_command ${SUDO}dnf install $options $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    gentoo*:install)
        [ -n "$system_packages" ] && print_shell_command ${SUDO}emerge $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    @(arch|msys|mingw)*:update)
        print_shell_command "${SUDO}pacman -Sy"
        ;;
    @(arch|msys|mingw)*:install)
        [ "$YES" = yes ] && options="$options --noconfirm"
        if [ "$IGNORE_MISSING" = yes ]; then
            [ -n "$system_packages" ] && echo "for pkg in $system_packages; do ${SUDO}pacman -S $options \$pkg || true; done"
        else
            [ -n "$system_packages" ] && print_shell_command ${SUDO}pacman -S $options $system_packages
        fi
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    void*:update)
        print_shell_command "${SUDO}xbps-install -Su"
        ;;
    void*:install)
        [ "$YES" = yes ] && options="$options --yes"
        [ -n "$system_packages" ] && print_shell_command ${SUDO}xbps-install $options $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    opensuse*:install)
        [ "$YES" = yes ] && options_pre="--non-interactive"
        [ "$IGNORE_MISSING" = yes ] && options_pre="$options_pre --ignore-unknown"
        [ -n "$system_packages" ] && print_shell_command ${SUDO}zypper $options_pre install $options $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    *conda*:install)
        [ "$YES" = yes ] && options="$options --yes"
        [ -n "$system_packages" ] && print_shell_command conda install $options $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    homebrew*:install)
        [ "$YES" = yes ] && options="$options --overwrite"
        [ -n "$system_packages" ] && print_shell_command brew install $options $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    macports*:install)
        [ "$YES" = yes ] && options="$options -N"
        [ -n "$system_packages" ] && print_shell_command ${SUDO}port $options install $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    slackware*:install)
        [ -n "$system_packages" ] && print_shell_command ${SUDO}slackpkg install $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    freebsd*:install)
        [ -n "$system_packages" ] && print_shell_command ${SUDO}pkg install $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    nix*:install)
        [ -n "$system_packages" ] && print_shell_command "nix-env -f '<nixpkgs>' --install --attr $system_packages"
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    alpine:update)
        print_shell_command "apk update"
        ;;
    alpine:install)
        if [ "$IGNORE_MISSING" = yes ]; then
            [ -n "$system_packages" ] && echo "for pkg in $system_packages; do apk add \$pkg || true; done"
        else
            [ -n "$system_packages" ] && print_shell_command apk add $system_packages
        fi
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    pip:install)
        [ -n "$system_packages" ] && print_shell_command pip install $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    cpan:install)
        [ -n "$system_packages" ] && print_shell_command cpan -i $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    spkg:install)
        [ -n "$system_packages" ] && print_shell_command sage -i $system_packages
        if [ -z "$system_packages" ]; then
            print_comment "No package needed"
        fi
        ;;
    repology:install)
        if [ -n "$system_packages" ]; then
            links=""
            for pkg in $system_packages; do
                link="https://repology.org/project/$pkg/versions"
                if [ -n "$links" ]; then
                    links="$links, "
                fi
                links="$links$link"
            done
            print_comment "See ${links}"
        fi
        ;;
    *:update)
        # Nothing needed
        ;;
    *)
        print_comment "$command the following packages: $system_packages"
        ;;
esac
