#!/usr/bin/env bash
#
#  __               ___
# /\ \            /'  __`
# \ \ \           \ \ \__
#  \_\ \   ______  \ \ ,_\ _____     __      ___
# /'__  \ /\ '__ \`\\ \ \//\ '__`\ /'__`\   /'___\
#/\ \L\. \\ \ \ \ \ \\ \ \\ \ \L\ /\ \L\.\_/\ \__/
#\ \__/.\__\ \ , \ \ \\ \__\ \ ,__\ \__/.\_\ \____\
# \/__/\/__/\/__\ \/_/ \/__/\ \ \/ \/__/\/_/\/____/
#                             \ \_\
#                              \/_/
# A Pacman wrapper with syntax based on Fedora's DNF
# Copyright (c) 2022-2023 Radio New Japan Broadcasting Network.
# License: Do What The Fuck You Want To Public License
# maintained by Hayate Nakamura

# Enter the path to the AUR helper you want to use here. 
# If it is empty, the corresponding AUR helper will be searched automatically.
#AURHELPER=

set -e


# DNFPac Version
DNFPAC_VERSION="0.1.1"

# Initialise List
PACMAN_PACKAGE_FILE=()
PACMAN_PACKAGE=()
RPM_PACKAGE_FILE=()

# PACMAN Config
HELPERS=(
    "/usr/bin/yay"
    "/usr/bin/paru"
    "/usr/bin/yaourt"
    "/usr/bin/aurman"
    "/usr/bin/pikaur"
    "/usr/bin/pacaur"
    "/usr/bin/aura"
    "/usr/bin/wfa"
)
PACMAN_OPTIONS=()
DEFAULT_PACMAN_COMMAND="/usr/bin/pacman"
PACMAN_COMMAND="${DEFAULT_PACMAN_COMMAND}"
PACMAN_CONFIG="/etc/pacman.conf"

# DNFPac Config
#DEBTAP_WORK="/tmp/aptpac-debtap"
DEBUG=false
RUN_WITH_SUDO=false
DIRECT_PACMAN=false
AUTOREMOVE=false
INSTALL=false

_msg_error () {
    echo -e "${@}" >&2
}

_msg_warn () {
    echo -e "${@}" >&2
}

_msg_debug () {
    if "${DEBUG}"; then
        echo -e "${@}" >&1
    fi
}


# List option
INSTALLED_PKGLIST=false

_usage () {
    echo "usage ${0} [options] [command] [packages]"
    echo
    echo " dnf commands:"
    echo "    install                              Install the specified package"
    echo "    remove                               Remove the specified package"
    echo "    erase                                Permanently remove the package"
    echo "    update                               Update package database"
    echo "    upgrade                              Update packages"
    echo "    search                               Search for a package"
    echo "    autoremove                           Remove unnecessary packages"
    echo "    clean                                Remove the package cache"
    echo "    list                                 Display a list of packages"
    echo "    info                                 Display the package records"
    echo "    repoquery                            Display the dependencies"
    echo
    echo " dnf options:"
    echo "    -y | --yes  | --assumeyes            Do not check"
    echo "    --downloadonly                       Only download the package"
    echo "    -c | --config-file <file>            Config file for pacman"
    echo "    -h | --help                          Display this help"
    echo "    -v | --version                       Display the version of dnfpac and pacman"
    echo "         --autoremove                    Remove unnecessary packages with other command"
    echo "         --erase                         Delete the entire configuration file"
    echo
    echo " pacdnf options:"
    echo "         --aur-helper <command>          Specifies the command to use as the AUR helper"
    echo "                                         Ignored if pacdnf is run as root"
    echo "                                         Specify AUR helper that supports common command line options with pacman"
    echo "         --pflags <flags>                Pass arguments to pacman"
    echo
#    echo " Notes:"
#    echo "    - dnfpac supports not only above options but also options of pacman"
#    echo "    - If you specify the deb file, you can install using debtap"
}

_exit () {
    exit "${1}"
}

_version () {
cat << EOF
DNFPac ${DNFPAC_VERSION} - A pacman wrapper with syntax based on fedora's dnf
License: Do What The Fuck You Want To Public License
(c) 2022-2023 Radio New Japan Broadcasting Club. Nakamura Hayate
EOF
    echo
    pacman --version
}

ADD_OPTION () {
    _msg_debug "Added pacman option '${*}'"
    PACMAN_OPTIONS+=("${@}")
}

_sudo(){
    if "${RUN_WITH_SUDO}"; then
        _msg_debug "Run sudo ${*}"
        eval sudo "${@}"
    else
        _msg_debug "Run ${*}"
        eval "${@}"
    fi
}

_pacman(){
    _sudo "${PACMAN_COMMAND}" "${PACMAN_OPTIONS[@]}" --config "${PACMAN_CONFIG}" "${@}"
}

_run_detect_aur_helper(){
    if [[ ! "${UID}" = 0 ]]; then
        if [[ -z "${AURHELPER+SET}" ]]; then
            for AURHELPER in "${HELPERS[@]}"; do
                if [[ -f "${AURHELPER}" ]]; then
                    PACMAN_COMMAND="${AURHELPER}"
                    break
                elif hash "$(basename "${AURHELPER}")" 2> /dev/null; then
                    PACMAN_COMMAND="$(basename "${AURHELPER}")"
                    break
                fi
            done
        else
            if [[ -f "${AURHELPER}" ]]; then
                PACMAN_COMMAND="${AURHELPER}"
            elif hash "$(basename "${AURHELPER}")" 2> /dev/null; then
                PACMAN_COMMAND="$(basename "${AURHELPER}")"
            else
                _msg_error "${AURHELPER} is not installed"
                exit 1
            fi
        fi
    fi
}

_run_aur_message(){
    if [[ ! "${PACMAN_COMMAND}" = "${DEFAULT_PACMAN_COMMAND}" ]] && [[ ! "$(basename "${PACMAN_COMMAND}")" = "$(basename "${DEFAULT_PACMAN_COMMAND}")" ]]; then
        _msg_debug "Use AUR helper ${PACMAN_COMMAND}"
    else
        RUN_WITH_SUDO=true
    fi
}

_run_autoremove(){
    if "${AUTOREMOVE}"; then
        if [[ -n $(${PACMAN_COMMAND} -Qttdq) ]]; then
            "${PACMAN_COMMAND}" -Qttdq | _sudo "${PACMAN_COMMAND}" -Rsc --config "${PACMAN_CONFIG}" -
        else
            echo "No packages to remove"
            exit 0
        fi
    fi
}

_run_distinguish_package(){
    local pkg
    for pkg in "${PACKAGE[@]}"; do
        if [[ ! -f "${pkg}" ]]; then
            PACMAN_PACKAGE+=("${pkg}")
        elif [[ "$(file -b --mime-type "${pkg}" 2> /dev/null)" = "application/vnd.debian.binary-package" ]]; then
            DEB_PACKAGE_FILE+=("${pkg}")
        else
            PACMAN_PACKAGE_FILE+=("${pkg}")
        fi
    done
}

_run_pacman(){
    if [[ "${INSTALL}" = true ]]; then
        _pacman -S "${PACMAN_PACKAGE[@]}"
    else
        _pacman "${PACMAN_PACKAGE[@]}"
    fi
}

#_run_debtap(){
#    _msg_warn "It is not recommended to install deb package"
#    _msg_warn "The package conversion is not perfect and can lead to errors in some cases"
#
#    if (( "${#DEB_PACKAGE_FILE[@]}" != 0 )) && ! hash "debtap"; then
#        _msg_error "debtap was not found"
#        exit 1
#    fi
#
#    if [[ -z "$(find "/var/cache/pkgfile" -maxdepth 1 -mindepth 1 -name "*.files" 2> /dev/null)" ]] || [[ -z "$(find "/var/cache/debtap" -maxdepth 1 -mindepth 1 -name "*-packages" 2> /dev/null)" ]] || [[ -z "$(find "/var/cache/debtap" -maxdepth 1 -mindepth 1 -name "*-files" 2> /dev/null)" ]]; then
#        _msg_debug "Updating debtap datebase"
#        sudo debtap -u
#    fi
#
#    (
#        sudo mkdir -p "${DEBTAP_WORK}"
#        local pkg work
#        for pkg in "${DEB_PACKAGE_FILE[@]}"; do
#            work="${DEBTAP_WORK}/$(basename "${pkg}")/"
#            file="${work}/$(basename "${pkg}")"
#            _msg_debug "Work dir: ${work}"
#            _msg_debug "Deb file:${work}"
#            sudo mkdir -p "${work}"
#            sudo cp "${pkg}" "${file}"
#            cd "${work}"
#            sudo debtap --Quiet "${file}"
#            while read -r archpkg; do
#                _msg_debug "Install ${archpkg} with pacman"
#                _pacman -U "${archpkg}"
#            done < <(find "${work}" -maxdepth 1 -mindepth 1 -type f -name "*.pkg.tar.*")
#        done
#    )
#}


# Argument analysis and processing
set +e
PACDNF_ARGUMENTS=("${@}")
_opt_short="ydfc:hvVDFQRSTU"
_opt_long="yes,assume-yes,download-only,fix-broken,erase,installed,debug,help,version,config-file:,auto-remove,autoremove,aur-helper:,pflags:,all"
OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- "${@}" 2> /dev/null)
set -e
#if [[ ${?} != 0 ]]; then
#    exit 1
#fi

eval set -- "${OPT}"
#echo "Argument is \"${OPT}\""
unset OPT _opt_short _opt_long

while true; do
    case "${1}" in
        -y | --yes | --assumeyes)
            ADD_OPTION "--noconfirm"
            shift 1
            ;;
        -d | --downloadonly)
            ADD_OPTION "-w"
            shift 1
            ;;
        -f | --fix-broken)
            shift 1
            ;;
        -c | --config-file)
            PACMAN_CONFIG="${2}"
            shift 2
            ;;
        all)
            ALLCLEAN=true
            shift 1
            ;;
        --erase)
            ADD_OPTION "-n"
            shift 1
            ;;
        --installed)
            INSTALLED_PKGLIST=true
            shift 1
            ;;
        --debug)
            DEBUG=true
            shift 1
            ;;
        -h | --help)
            _usage
            shift 1
            exit 0
            ;;
        -v | --version)
            _version
            shift 1
            exit 0
            ;;
        --autoremove)
            AUTOREMOVE=true
            shift 1
            ;;
        --aur-helper)
            if [[ ! "${UID}" = 0 ]] && [[ -f "${2}" ]]; then
                PACMAN_COMMAND="${2}"
            elif [[ "${UID}" = 0 ]]; then
                _msg_warn "The specified AUR helper is not used because pacdnf is running on the root."
            elif hash "$(basename "${2}")" 2> /dev/null; then
                PACMAN_COMMAND="$(basename "${2}")"
            else
                _msg_error "${2} is not installed"
                exit 1
            fi
            shift 2
            ;;
        --pflags)
            # shellcheck disable=SC2086
            ADD_OPTION ${2}
            shift 2
            ;;
        -V | -D | -F | -Q | -R | -S | -T | -U)
            DIRECT_PACMAN=true
            ADD_OPTION "${PACDNF_ARGUMENTS[@]}"
            break
            ;;
        --)
            shift 1
            break
            ;;
        *)
            _msg_error "Invalid argument '${1}'"
            _help
            exit 1
            ;;
    esac
done

if [[ "${DIRECT_PACMAN}" = false ]]; then
    if [[ $# -lt 1 ]]; then
        _msg_error "No command specified"
        _usage
        _exit 1
    fi
    COMMAND="${1,,}"

    shift 1

    PACKAGE=("${@}")

    case "${COMMAND}" in
        install)
            #ADD_OPTION "-S"
            INSTALL=true
            ;;
        remove)
            ADD_OPTION "-Rsc"
            ;;
        erase)
            ADD_OPTION "-Rnsc"
            ;;
        update)
            ADD_OPTION "-Syy"
            ;;
        upgrade)
            ADD_OPTION "-Syu"
            ;;
        search)
            ADD_OPTION "-Ss"
            ;;
        clean)
            if [[ ${1} = all ]]; then
                ADD_OPTION "-Scc"
            else
                ADD_OPTION "-Sc"
            fi
            ;;
        huawei) 
            # shellcheck disable=SC1091
            if [[ "$(source "/etc/locale.conf" 2> /dev/null; echo -n "${LANG}")" = "ja_JP.UTF-8" ]]; then
                echo "(ง •ᴗ•)ว ⁾⁾ﾌｧｰｳｪｲでｳｪｲｳｪｲ"
                _exit 0
            else
                _msg_error "Invalid command '${COMMAND}'"
                _exit 1
            fi
            ;;
        autoremove) 
            if [[ -n "$(${PACMAN_COMMAND} -Qtdq)" ]]; then
                ADD_OPTION "-Rsc"
                while read -r pkg; do
                    PACKAGE+=("${pkg}")
                done < <(${PACMAN_COMMAND} -Qttdq)
            else
                echo "No packages to remove"
                exit 0
            fi
            ;;
        list)
            if [[ "${INSTALLED_PKGLIST}" = true ]]; then
                ADD_OPTION "-Q | grep"
            else
                ADD_OPTION "-Ss"
            fi
            ;;
        info)
            for pkg in "${PACKAGE[@]}"; do
                if pacman -Qq "${pkg}" 2> /dev/null 1>&2; then
                    "${PACMAN_COMMAND}" "${PACMAN_OPTIONS[@]}" -Qi --config "${PACMAN_CONFIG}" "${pkg}"
                else
                    "${PACMAN_COMMAND}" "${PACMAN_OPTIONS[@]}" -Si --config "${PACMAN_CONFIG}" "${pkg}"
                fi
            done
            unset pkg
            _exit 0
            ;;
        repoquery)
            ADD_OPTION "-Sii"
            ;;
        help)
            _usage
            exit 0
            ;;
        *)
            _msg_error "Invalid command '${COMMAND}'"
            _exit 1
            ;;
    esac
fi


_run_detect_aur_helper
_run_aur_message
_run_distinguish_package
_run_pacman
#if [[ "${INSTALL}" = true ]]; then
#    _run_debtap  
#fi
_run_autoremove
