#!/bin/bash

#
# pacaur: a fast workflow AUR helper using cower as backend
#

version="4.2.25"

#
# Config
#

# internationalization
LC_COLLATE=C                                # getopts sorting
TEXTDOMAIN='pacaur'
TEXTDOMAINDIR='/usr/share/locale'

# source makepkg variables
source /etc/makepkg.conf
[[ -r "$HOME/.makepkg.conf" ]] && source "$HOME/.makepkg.conf"

# set variables
tmpdir="${TMPDIR:-/tmp}/pacaurtmp-$USER"    # temp directory
builddir="${BUILDDIR:-$tmpdir}"             # build directory
editor="${EDITOR:-vi}"                      # PKGBUILD editor
editpkgbuild=true                           # edit PKGBUILD
editinstall=true                            # edit install script
fallback=true                               # pacman fallback to the AUR
clean=true                                  # cleanup after install
cleandevel=true                             # cleanup devel after install
sortbyvotes=true                            # sort search results by votes
sudoloop=false                              # prevent sudo timeout

# set pacman binary
pacmanbin="${PACMAN:-pacman}"

# source xdg config
if [[ -n "${XDG_CONFIG_DIRS}" ]]; then
    xdg_config=($(awk -F ":" '{for (i=1; i<=NF; i++) print $i}' <<< ${XDG_CONFIG_DIRS}))
    for i in "${xdg_config[@]}"; do
        [[ -d "$i" ]] && export XDG_CONFIG_DIRS="$i" && break
    done
fi
configdir="${XDG_CONFIG_DIRS:-/etc/xdg}/pacaur"
userconfigdir="${XDG_CONFIG_HOME:-${HOME}/.config}/pacaur"
source "$configdir/config"
[[ -r "$userconfigdir/config" ]] && source "$userconfigdir/config"

# set up directories
[[ -d "$tmpdir" ]] && [[ ! -w "$tmpdir" ]] && sudo rm -rf "$tmpdir"
[[ ! -d "$tmpdir" ]] && mkdir -p "$tmpdir"
[[ ! -d "$builddir" ]] && mkdir -p "$builddir"

#
# Functions
#

ClassifyPkgs() {
    if [[ $fallback = true ]]; then
        [[ $repo ]] && repopkgs=(${pkgs[@]})
        [[ $aur ]] && aurpkgs=(${pkgs[@]})
        if [[ ! $repo && ! $aur ]]; then
            unset noaurpkgs
            for i in "${pkgs[@]}"; do
                [[ $i == aur/* ]] && aurpkgs+=(${i:4}) && continue # search aur/pkgs in AUR
                noaurpkgs+=($i)
            done
            [[ -n "${noaurpkgs[@]}" ]] && norepopkgs=($(LANG=C $pacmanbin -Sp ${noaurpkgs[@]} 2>&1 >/dev/null | awk -F " " '{print $NF}'))
            for i in "${norepopkgs[@]}"; do
                [[ ! " ${noaurpkgs[@]} " =~ [a-zA-Z0-9\.\+-]+\/$i[^a-zA-Z0-9\.\+-] ]] && aurpkgs+=($i) # do not search repo/pkgs in AUR
            done
            repopkgs=($(LC_COLLATE=C comm -23 <(tr ' ' '\n' <<< ${noaurpkgs[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${aurpkgs[@]} | LC_COLLATE=C sort -u)))
        fi
    else
        [[ ! $aur ]] && repopkgs=(${pkgs[@]}) || aurpkgs=(${pkgs[@]})
    fi
}

Core() {
    getignoredpkgs
    [[ $upgrade ]] && UpgradeAur
    IgnoreChecks
    DepsSolver
    IgnoreDepsChecks
    ProviderChecks
    ConflictChecks
    ReinstallChecks
    OutofdateChecks
    Prompt
    DownloadPkgs
    MakePkgs
}

UpgradeAur() {
    note "i" $"${colorW}Starting AUR upgrade...${reset}"
    [[ -e "$tmpdir/ignoretmp" ]] && rm "$tmpdir/ignoretmp"
    aurpkgs+=($(cower -u ${coweropts[@]} ${pkgs[@]} 2>"$tmpdir/ignoretmp" | sed -r "s:\x1B\[[0-9;]*[mK]::g" | awk -F " " '{print $2}'))
    [[ -e "$tmpdir/ignoretmp" ]] && aurpkgs+=($(awk -F " " '{print $2}' "$tmpdir/ignoretmp" | sed -r "s:\x1B\[[0-9;]*[mK]::g"))

    # foreign packages check
    foreignpkgs=($($pacmanbin -Qmq))
    downloadjson ${foreignpkgs[@]}
    allaurpkgs=($(getjsonvar "Name"))
    aurforeignpkgs=($(LC_COLLATE=C comm -23 <(tr ' ' '\n' <<< ${foreignpkgs[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${allaurpkgs[@]} | LC_COLLATE=C sort -u)))
    for i in "${aurforeignpkgs[@]}"; do
        note "w" $"${colorW}$i${reset} is ${colorY}not present${reset} in AUR -- skipping"
    done

    # add devel packages
    if [[ $devel ]]; then
        for i in "${allaurpkgs[@]}"; do
            [[ -n "$(grep -E "\-(cvs|svn|git|hg|bzr|darcs|nightly.*)$" <<< $i)" ]] && aurpkgs+=($i)
        done
    fi

    # avoid possible duplicate
    aurpkgs=($(tr ' ' '\n' <<< ${aurpkgs[@]} | sort -u))

    nothingtodo ${aurpkgs[@]}
}

IgnoreChecks() {
    [[ -z "${ignoredpkgs[@]}" ]] && return

    checkaurpkgs=(${aurpkgs[@]})
    unset aurpkgs

    # check targets
    downloadjson ${checkaurpkgs[@]}
    checkaurpkgsAname=($(getjsonvar "Name"))    # return sorted results
    checkaurpkgsAver=($(getjsonvar "Version"))
    checkaurpkgsQver=($(expac -Q '%v' "${checkaurpkgsAname[@]}"))
    for ((i=0; i<${#checkaurpkgsAname[@]}; i++)); do
        [[ -n "$(grep -E "\-(cvs|svn|git|hg|bzr|darcs|nightly.*)$" <<< ${checkaurpkgsAname[$i]})" ]] && checkaurpkgsAver[$i]=$"latest"
    done
    for ((i=0; i<${#checkaurpkgs[@]}; i++)); do
        if [[ " ${ignoredpkgs[@]} " =~ " ${checkaurpkgs[$i]} " ]]; then
            if [[ ! $upgrade && ! $noconfirm ]]; then
                if ! proceed "y" $"${checkaurpkgs[$i]} is in IgnorePkg/IgnoreGroup. Install anyway?"; then
                    note "w" $"${colorW}${checkaurpkgs[$i]}${reset}: ignoring package upgrade"
                    rmaurpkgs+=(${checkaurpkgs[$i]})
                    continue
                fi
            else
                note "w" $"${colorW}${checkaurpkgs[$i]}${reset}: ignoring package upgrade (${colorR}${checkaurpkgsQver[$i]}${reset} => ${colorG}${checkaurpkgsAver[$i]}${reset})"
                rmaurpkgs+=(${checkaurpkgs[$i]})
                continue
            fi
        fi
        aurpkgs+=(${checkaurpkgs[$i]})
    done

    nothingtodo ${aurpkgs[@]}
}

DepsSolver() {
    note "i" $"resolving dependencies..."

    # remove AUR pkgs versioning
    for ((i=0; i<${#aurpkgs[@]}; i++)); do
        aurpkgs[$i]=$(awk -F ">|<|=" '{print $1}' <<< ${aurpkgs[$i]})
    done
    deps+=(${aurpkgs[@]})

    FindDepsAur ${aurpkgs[@]}

    # get AUR packages info
    downloadjson ${deps[@]}
    depsAname=($(getjsonvar "Name"))    # return sorted results
    depsAver=($(getjsonvar "Version"))
    depsAood=($(getjsonvar "OutOfDate"))
    for ((i=0; i<${#depsAname[@]}; i++)); do
        depsQver[$i]=$(expac -Qs '%v' "^${depsAname[$i]}$")
        [[ -z "${depsQver[$i]}" ]] && depsQver[$i]="#"  # avoid empty elements shift
        [[ -n "$(grep -E "\-(cvs|svn|git|hg|bzr|darcs|nightly.*)$" <<< ${depsAname[$i]})" ]] && depsAver[$i]=$"latest"
    done

    # hard check for AURINFO metadata
    depsAlastmodified=($(getjsonvar "LastModified"))
    for ((i=0; i<${#depsAlastmodified[@]}; i++)); do
        # first package submitted to AUR 3.0.0 on 2014-05-27 18:35
        [[ "${depsAlastmodified[$i]}" -lt 1401215749 ]] && note "f" $"no AUR metadata for ${colorR}${depsAname[$i]}${reset} package"
    done

    # no results check
    for i in "${errdeps[@]}"; do
        note "f" $"no results found for $i"
    done
    [[ -n "${errdeps[@]}" ]] && exit 1

    # return all binary deps
    FindDepsRepo ${repodeps[@]}
}

FindDepsAur() {
    [[ $nodeps && $count -ge 2 ]] && return
    [[ -z "${depspkgsaur[@]}" ]] && depspkgsaur=(${aurpkgs[@]})

    downloadjson ${depspkgsaur[@]}

    # target check
    [[ -z "${prevdepspkgsaur[@]}" ]] && errdeps+=($(LC_COLLATE=C comm -3 <(tr ' ' '\n' <<< $(getjsonvar "Name") | sort -u) <(tr ' ' '\n' <<< ${aurpkgs[@]} | sort -u)))

    # AUR versioning check
    if [[ -n "${prevdepspkgsaur[@]}" ]]; then
        for ((i=0; i<${#prevdepspkgsaur[@]}; i++)); do
            case "${prevdepspkgsaur[$i]}" in
                *">"*|*"<"*|*"="*)
                    unset prevname prevver prevaurver
                    prevname=${prevdepspkgsaur[$i]} && prevname=${prevname%[><]*} && prevname=${prevname%=*}
                    prevver=${prevdepspkgsaur[$i]} && prevver=${prevver#*=} && prevver=${prevver#*[><]}
                    prevaurver=($(getjsonvarvar "Version" "$prevname"))

                    # not found in AUR nor repo
                    if [[ ! $prevaurver ]]; then
                        [[ ! " ${errdeps[@]} " =~ " ${prevdepspkgsaur[$i]} " ]] && errdeps+=(${prevdepspkgsaur[$i]})
                        continue
                    fi

                    # found in AUR but version not correct
                    case "${prevdepspkgsaur[$i]}" in
                        *">="*) [[ $(vercmp "$prevaurver" "$prevver") -ge 0 ]] && continue;;
                        *"<="*) [[ $(vercmp "$prevaurver" "$prevver") -le 0 ]] && continue;;
                        *">"*)  [[ $(vercmp "$prevaurver" "$prevver") -gt 0 ]] && continue;;
                        *"<"*)  [[ $(vercmp "$prevaurver" "$prevver") -lt 0 ]] && continue;;
                        *"="*)  [[ $(vercmp "$prevaurver" "$prevver") -eq 0 ]] && continue;;
                    esac
                    [[ ! " ${errdeps[@]} " =~ " ${prevdepspkgsaur[$i]} " ]] && errdeps+=(${prevdepspkgsaur[$i]})
                ;;
                *) continue;;
            esac
        done
    fi

    depspkgs=($(getjsonarray "Depends"))

    # cached packages makedeps check
    if [[ ! $PKGDEST || $rebuild ]]; then
        depspkgs+=($(getjsonarray "MakeDepends"))
    else
        for ((i=0; i<${#depspkgsaur[@]}; i++)); do
            depsAname=$(getjsonvarvar "Name" "${depspkgsaur[$i]}")
            depsAver=$(getjsonvarvar "Version" "${depspkgsaur[$i]}")
            getcachedpkg "$depsAname-$depsAver" "$PKGDEST"
            [[ ! $cachedpkg ]] && depspkgs+=($(getjsonarrayvar "MakeDepends" "${depspkgsaur[$i]}"))
            unset cachedpkg
        done
    fi

    # remove installed deps
    depspkgs=($($pacmanbin -T ${depspkgs[@]} | sort -u))

    # split binary and AUR depends pkgs
    unset depspkgsaur
    if [[ -n "${depspkgs[@]}" ]]; then
        # remove all pkgs versioning
        if [[ $nodeps && $count -eq 1 ]]; then
            for ((i=0; i<${#depspkgs[@]}; i++)); do
                depspkgs[$i]=$(awk -F ">|<|=" '{print $1}' <<< ${depspkgs[$i]})
            done
        fi
        depspkgsaur=($(LANG=C $pacmanbin -Sp ${depspkgs[@]} 2>&1 >/dev/null | awk -F " " '{print $NF}'))
        repodeps+=($(LC_COLLATE=C comm -23 <(tr ' ' '\n' <<< ${depspkgs[@]} | LC_COLLATE=C sort -u)  <(tr ' ' '\n' <<< ${depspkgsaur[@]} | LC_COLLATE=C sort -u)))
    fi
    unset depspkgs

    if [[ -n "${depspkgsaur[@]}" ]]; then
        # store for AUR version check
        [[ ! $nodeps ]] && prevdepspkgsaur=(${depspkgsaur[@]})

        # remove AUR pkgs versioning
        for ((i=0; i<${#depspkgsaur[@]}; i++)); do
            depspkgsaur[$i]=$(awk -F ">|<|=" '{print $1}' <<< ${depspkgsaur[$i]})
        done

        # ensure correct dependency order
        depspkgsaur=($(tr ' ' '\n' <<< ${depspkgsaur[@]} | sort -u))
        for ((i=0; i<${#depspkgsaur[@]}; i++)); do
            if [[ " ${deps[@]} " =~ " ${depspkgsaur[$i]} " ]]; then
                deps=($(tr ' ' '\n' <<< ${deps[@]} | sed "s/^${depspkgsaur[$i]}$//g"))
                aurdepspkgs=($(tr ' ' '\n' <<< ${aurdepspkgs[@]} | sed "s/^${depspkgsaur[$i]}$//g"))
            fi
        done
    fi

    if [[ -n "${depspkgsaur[@]}" ]]; then
        aurdepspkgs+=(${depspkgsaur[@]})
        deps+=(${depspkgsaur[@]})
        FindDepsAur ${depspkgsaur[@]}
    fi
}

FindDepsRepo() {
    [[ -z "${repodeps[@]}" ]] && return

    # reduce root binary deps
    repodeps=($(tr ' ' '\n' <<< ${repodeps[@]} | sort -u))

    for i in "${repodeps[@]}"; do
        allrepopkgs+=($(pactree -su "$i"))
    done

    if [[ -n "${allrepopkgs[@]}" ]]; then
        providersrepopkgs=($(LC_COLLATE=C comm -23 <(tr ' ' '\n' <<< ${allrepopkgs[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< $(expac -S '%n' "${allrepopkgs[@]}") | LC_COLLATE=C sort -u)))
    fi

    # remove pactree deps of default providers if non default provider is already installed
    if [[ -n "${providersrepopkgs[@]}" ]]; then
        for i in "${providersrepopkgs[@]}"; do
            j=$(expac -Qs '%n' "^$i$")
            [[ -n "$j" ]] && [[ "$j" != "$(expac -Ss '%n' "^$i$" | tr '\n' ' ' | awk -F " " '{print $1}')" ]] && providersrepopkgsrm+=($(pactree -su "$i"))
        done
        if [[ -n "${providersrepopkgsrm[@]}" ]]; then
            providersrepopkgsrm=($($pacmanbin -T ${providersrepopkgsrm[@]} | sort -u))
            allrepopkgs=($(LC_COLLATE=C comm -23 <(tr ' ' '\n' <<< ${allrepopkgs[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${providersrepopkgsrm[@]} | LC_COLLATE=C sort -u)))
        fi
    fi

    repodepspkgs=($($pacmanbin -T ${allrepopkgs[@]} | sort -u))
}

IgnoreDepsChecks() {
    [[ -z "${ignoredpkgs[@]}" ]] && return

    # add checked targets
    deps=(${aurpkgs[@]})

    # check dependencies
    for i in "${repodepspkgs[@]}"; do
        if [[ " ${ignoredpkgs[@]} " =~ " $i " ]]; then
            note "w" $"${colorW}$i${reset}: ignoring package upgrade"
            note "e" $"Unresolved dependency '${colorW}$i${reset}'"
        fi
    done
    for i in "${aurdepspkgs[@]}"; do
        # skip already checked dependencies
        [[ " ${aurpkgs[@]} " =~ " $i " ]] && continue
        [[ " ${rmaurpkgs[@]} " =~ " $i " ]] && note "e" $"Unresolved dependency '${colorW}$i${reset}'"

        if [[ " ${ignoredpkgs[@]} " =~ " $i " ]]; then
            if [[ ! $noconfirm ]]; then
                if ! proceed "y" $"$i dependency is in IgnorePkg/IgnoreGroup. Install anyway?"; then
                    note "e" $"Unresolved dependency '${colorW}$i${reset}'"
                fi
            else
                note "w" $"${colorW}$i${reset}: ignoring package upgrade"
                note "e" $"Unresolved dependency '${colorW}$i${reset}'"
            fi
        fi
        deps+=($i)
    done
}

ProviderChecks() {
    [[ -z "${repodepspkgs[@]}" ]] && return

    allproviders=($(expac -S '%S' "${repodepspkgs[@]}" | sort -u))
    # remove installed providers
    providersdeps=($($pacmanbin -T ${allproviders[@]} | sort -u))

    for ((i=0; i<${#providersdeps[@]}; i++)); do
        providers=($(expac -Ss '%n' "^${providersdeps[$i]}$" | sort -u))
        [[ ! ${#providers[@]} -gt 1 ]] && continue

        # skip if already provided
        if [[ -n "${providerspkgs[@]}" ]]; then
            providerspkgs=($(tr ' ' '|' <<< ${providerspkgs[@]}))
            provided+=($(expac -Ss '%S' "^(${providerspkgs[*]})$"))
            [[ " ${provided[@]} " =~ " ${providersdeps[$i]} " ]] && continue
        fi

        if [[ ! $noconfirm ]]; then
            note "i" $"${colorW}There are ${#providers[@]} providers available for ${providersdeps[$i]}:${reset}"
            expac -S -1 '   %!) %n (%r) ' "${providers[@]}"

            local nb=-1
            providersnb=$(( ${#providers[@]} -1 )) # count from 0
            while [[ $nb -lt 0 || $nb -ge ${#providers} ]]; do

                printf "\n%s " $"Enter a number (default=0):"
                read -n $(echo -n $providersnb | wc -m) nb
                echo

                case $nb in
                    [0-9]|[0-9][0-9]) [[ $nb -lt 0 || $nb -ge ${#providers[@]} ]] && echo && note "f" $"invalid value: $nb is not between 0 and $providersnb" && ((i--)) || break;;
                    '') nb=0;;
                    *) note "f" $"invalid number: $nb";;
                esac
            done
        else
            local nb=0
        fi
        providerpkgs+=(${providers[$nb]})
        [[ $nb -ne 0 ]] && rmproviderpkgs+=(${providersdeps[$i]})
    done

    # pactree always return default choice so update binary deps list
    if [[ -n "${rmproviderpkgs[@]}" ]]; then
        # remove deps of default providers
        for i in "${rmproviderpkgs[@]}"; do
            providerpkgsrm+=($(pactree -su "$i"))
        done
        providerpkgsrm=($($pacmanbin -T ${providerpkgsrm[@]} | sort -u))
        repodepspkgs=($(LC_COLLATE=C comm -23 <(tr ' ' '\n' <<< ${repodepspkgs[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${providerpkgsrm[@]} | LC_COLLATE=C sort -u)))

        # add deps of selected providers instead
        for i in "${providerpkgs[@]}"; do
            providerdeps+=($(pactree -su "$i"))
        done
        repodepspkgs+=($($pacmanbin -T ${providerdeps[@]} | sort -u))
    fi

    # get binary packages info
    if [[ -n "${repodepspkgs[@]}" ]]; then
        repodepspkgs=($(expac -S -1 '%n' "${repodepspkgs[@]}" | LC_COLLATE=C sort -u))
        repodepsSver=($(expac -S -1 '%v' "${repodepspkgs[@]}"))
        repodepsQver=($(expac -Q '%v' "${repodepspkgs[@]}"))
        repodepsSrepo=($(expac -S -1 '%r/%n' "${repodepspkgs[@]}"))
    fi
}

ConflictChecks() {
    note "i" $"looking for inter-conflicts..."

    allQprovides=($(expac -Q '%n'))
    allQprovides+=($(expac -Q '%S')) # no versioning
    allQconflicts=($(expac -Q '%C'))

    # AUR conflicts
    Aprovides=(${depsAname[@]})
    Aprovides+=($(getjsonarray "Provides"))
    Aconflicts=($(getjsonarray "Conflicts"))
    # remove AUR versioning
    for ((i=0; i<${#Aprovides[@]}; i++)); do
        Aprovides[$i]=$(awk -F ">|<|=" '{print $1}' <<< ${Aprovides[$i]})
    done
    for ((i=0; i<${#Aconflicts[@]}; i++)); do
        Aconflicts[$i]=$(awk -F ">|<|=" '{print $1}' <<< ${Aconflicts[$i]})
    done
    aurconflicts+=($(LC_COLLATE=C comm -12 <(tr ' ' '\n' <<< ${Aprovides[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${allQconflicts[@]} | LC_COLLATE=C sort -u)))
    aurconflicts+=($(LC_COLLATE=C comm -12 <(tr ' ' '\n' <<< ${Aconflicts[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${allQprovides[@]} | LC_COLLATE=C sort -u)))
    aurconflicts=($(tr ' ' '\n' <<< ${aurconflicts[@]} | LC_COLLATE=C sort -u))

    for i in "${aurconflicts[@]}"; do
        unset aurAconflicts
        [[ " ${depsAname[@]} " =~ " $i " ]] && aurAconflicts=($i)
        for j in "${depsAname[@]}"; do
            [[ " $(getjsonarrayvar "Conflicts" "$j") " =~ " $i " ]] && aurAconflicts+=($j)
        done

        for j in "${aurAconflicts[@]}"; do
            unset k Aprovides
            k=$(expac -Qs '%n' "^$i$")
            [[ ! $installpkg && ! " ${aurdepspkgs[@]} " =~ " $j " ]] && continue # skip if downloading target only
            [[ "$j" == "$k" || -z "$k" ]] && continue # skip if reinstalling or if no conflict exists

            Aprovides=($j)
            if [[ ! $noconfirm && ! " ${aurconflictingpkgs[@]} " =~ " $k " ]]; then
                if ! proceed "n" $"$j and $k are in conflict ($i). Remove $k?"; then
                    aurconflictingpkgs+=($j $k)
                    aurconflictingpkgsrm+=($k)
                    for ((l=0; l<${#depsAname[@]}; l++)); do
                        [[ " ${depsAname[$l]} " =~ "$k" ]] && depsQver[$l]=$(expac -Qs '%v' "^$k$")
                    done
                    Aprovides+=($(getjsonarrayvar "Provides" "$j"))
                    # remove AUR versioning
                    for ((i=0; i<${#Aprovides[@]}; i++)); do
                        Aprovides[$i]=$(awk -F ">|<|=" '{print $1}' <<< ${Aprovides[$i]})
                    done
                    [[ ! " ${Aprovides[@]} " =~ " $k " && ! " ${aurconflictingpkgsrm[@]} " =~ " $k " ]] && checkQrequires $k
                    break
                else
                    note "f" $"unresolvable package conflicts detected"
                    note "f" $"failed to prepare transaction (conflicting dependencies)"
                    note "e" $"$j and $k are in conflict"
                fi
            fi
            Aprovides+=($(getjsonarrayvar "Provides" "$j"))
            # remove AUR versioning
            for ((i=0; i<${#Aprovides[@]}; i++)); do
                Aprovides[$i]=$(awk -F ">|<|=" '{print $1}' <<< ${Aprovides[$i]})
            done
            [[ ! " ${Aprovides[@]} " =~ " $k " ]] && checkQrequires $k
        done
    done

    nothingtodo ${deps[@]}

    # repo conflicts
    if [[ -n "${repodepspkgs[@]}" ]]; then
        repodepsprovides=(${repodepspkgs[@]})
        repodepsprovides+=($(expac -S '%S' "${repodepspkgs[@]}")) # no versioning
        repodepsconflicts=($(expac -S '%C' "${repodepspkgs[@]}"))
        repoconflicts+=($(LC_COLLATE=C comm -12 <(tr ' ' '\n' <<< ${repodepsprovides[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${allQconflicts[@]} | LC_COLLATE=C sort -u)))
        repoconflicts+=($(LC_COLLATE=C comm -12 <(tr ' ' '\n' <<< ${repodepsconflicts[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${allQprovides[@]} | LC_COLLATE=C sort -u)))
        repoconflicts=($(tr ' ' '\n' <<< ${repoconflicts[@]} | LC_COLLATE=C sort -u))
    fi

    for i in "${repoconflicts[@]}"; do
        unset Qprovides
        repoSconflicts=($(expac -S '%n %C %S' "${repodepspkgs[@]}" | grep -E "[^a-zA-Z0-9_@\.\+-]$i" | grep -E "($i[^a-zA-Z0-9\.\+-]|$i$)" | awk -F " " '{print $1}'))
        for j in "${repoSconflicts[@]}"; do
            unset k && k=$(expac -Qs '%n' "^$i$")
            [[ -z "$k" ]] && continue # skip when no conflict with repopkgs

            if [[ ! $noconfirm && ! " ${repoconflictingpkgs[@]} " =~ " $k " ]]; then
                if ! proceed "n" $"$j and $k are in conflict ($i). Remove $k?"; then
                    repoconflictingpkgs+=($j $k)
                    repoconflictingpkgsrm+=($k)
                    Qprovides=($(expac -Ss '%S' "^$k$"))
                    [[ ! " ${Qprovides[@]} " =~ " $k " && ! " ${repoconflictingpkgsrm[@]} " =~ " $k " ]] && checkQrequires $k
                    break
                else
                    note "f" $"unresolvable package conflicts detected"
                    note "f" $"failed to prepare transaction (conflicting dependencies)"
                    note "e" $"$j and $k are in conflict"
                fi
            fi
            Qprovides=($(expac -Ss '%S' "^$k$"))
            [[ ! " ${Qprovides[@]} " =~ " $k " ]] && checkQrequires $k
        done
    done
}

ReinstallChecks() {
    depsAtmp=(${depsAname[@]})
    for ((i=0; i<${#depsAtmp[@]}; i++)); do
        [[ ! " ${aurpkgs[@]} " =~ " ${depsAname[$i]} " || " ${aurconflictingpkgs[@]} " =~ " ${depsAname[$i]} " ]] && continue
        [[ -z "${depsQver[$i]}" || "${depsQver[$i]}" = '#' || $(vercmp "${depsAver[$i]}" "${depsQver[$i]}") -gt 0 ]] && continue
        [[ ! $installpkg && ! " ${aurdepspkgs[@]} " =~ " ${depsAname[$i]} " ]] && continue
        if [[ -n "$(grep -E "\-(cvs|svn|git|hg|bzr|darcs|nightly.*)$" <<< ${depsAname[$i]})" ]]; then
            note "w" $"${colorW}${depsAname[$i]}${reset} latest revision -- fetching"
        else
            if [[ ! $needed ]]; then
                note "w" $"${colorW}${depsAname[$i]}-${depsQver[$i]}${reset} is up to date -- reinstalling"
            else
                note "w" $"${colorW}${depsAname[$i]}-${depsQver[$i]}${reset} is up to date -- skipping"
                deps=($(tr ' ' '\n' <<< ${deps[@]} | sed "s/^${depsAname[$i]}$//g"))
                unset depsAname[$i] depsQver[$i] depsAver[$i] depsAood[$i]
            fi
        fi
    done
    [[ $needed ]] && depsAname=(${depsAname[@]}) && depsQver=(${depsQver[@]}) && depsAver=(${depsAver[@]}) && depsAood=(${depsAood[@]})

    nothingtodo ${deps[@]}
}

OutofdateChecks() {
    for ((i=0; i<${#depsAname[@]}; i++)); do
        [[ "${depsAood[$i]}" -gt 0 ]] && note "w" $"${colorW}${depsAname[$i]}-${depsAver[$i]}${reset} has been flagged ${colorR}out of date${reset} on ${colorY}$(date -d "@${depsAood[$i]}" "+%Y-%m-%d")${reset}"
    done
}

Prompt() {
    # compute binary size
    if [[ -n "${repodepspkgs[@]}" ]]; then
        binaryksize=($(expac -S -1 '%k' "${repodepspkgs[@]}"))
        binarymsize=($(expac -S -1 '%m' "${repodepspkgs[@]}"))
        sumk=0
        summ=0
        for ((i=0; i<${#repodepspkgs[@]}; i++)); do
            getcachedpkg "${repodepspkgs[$i]}-${repodepsSver[$i]}" '/var/cache/pacman/pkg'
            [[ $cachedpkg ]] && binaryksize=(${binaryksize[@]/${binaryksize[$i]}/0})
            sumk=$((sumk + ${binaryksize[$i]}))
            summ=$((summ + ${binarymsize[$i]}))
        done
        sumk=$(awk '{ printf("%.2f\n", $1/$2) }' <<< "$sumk 1048576")
        summ=$(awk '{ printf("%.2f\n", $1/$2) }' <<< "$summ 1048576")
    fi

    # cached packages check
    for ((i=0; i<${#depsAname[@]}; i++)); do
        [[ ! $PKGDEST || $rebuild ]] && break
        getcachedpkg "${depsAname[$i]}-${depsAver[$i]}" "$PKGDEST"
        [[ $cachedpkg ]] && cachedpkgs+=(${depsAname[$i]}) && depsAcached[$i]=$"(cached)" || depsAcached[$i]=""
        unset cachedpkg
    done

    if [[ -n "$(grep '^VerbosePkgLists' '/etc/pacman.conf')" ]]; then
        strname=$"Name"; stroldver=$"Old Version"; strnewver=$"New Version"; strsize=$"Download Size"
        depsArepo=(${depsAname[@]/#/aur/})
        lname=$(getlength ${depsArepo[@]} ${repodepsSrepo[@]} "$strname")
        lver=$(getlength ${depsQver[@]} ${depsAver[@]} ${repodepsQver[@]} ${repodepsSver[@]} "$stroldver" "$strnewver")
        lsize=$(getlength "$strsize")

        # local version column cleanup
        for ((i=0; i<${#deps[@]}; i++)); do
            [[ "${depsQver[$i]}" =~ '#' ]] && unset depsQver[$i]
        done
        # show detailed output
        printf "\n${colorY}%s${reset}\n\n" $"AUR Packages  (${#deps[@]}):"
        printf "${colorW}%-${lname}s  %-${lver}s  %-${lver}s${reset}\n\n" "$strname" "$stroldver" "$strnewver"
        for ((i=0; i<${#deps[@]}; i++)); do
            printf "%-${lname}s  ${colorR}%-${lver}s${reset}  ${colorG}%-${lver}s${reset}  %${lsize}s\n" "${depsArepo[$i]}" "${depsQver[$i]}" "${depsAver[$i]}" "${depsAcached[$i]}";
        done

        if [[ -n "${repodepspkgs[@]}" ]]; then
            for ((i=0; i<${#repodepspkgs[@]}; i++)); do
                binarysize[$i]=$(awk '{ printf("%.2f\n", $1/$2) }' <<< "${binaryksize[$i]} 1048576")
            done
            printf "\n${colorY}%s${reset}\n\n" $"Repo Packages (${#repodepspkgs[@]}):"
            printf "${colorW}%-${lname}s  %-${lver}s  %-${lver}s  %s${reset}\n\n" $"Name" $"Old Version" $"New Version" $"Download Size"
            for ((i=0; i<${#repodepspkgs[@]}; i++)); do
                printf "%-${lname}s  ${colorR}%-${lver}s${reset}  ${colorG}%-${lver}s${reset}  %${lsize}s\n" "${repodepsSrepo[$i]}" "${repodepsQver[$i]}" "${repodepsSver[$i]}" $"${binarysize[$i]} MiB";
            done
        fi
    else
        # show version
        for ((i=0; i<${#deps[@]}; i++)); do
            depsver="${depsver}${depsAname[$i]}-${depsAver[$i]}  "
        done
        for ((i=0; i<${#repodepspkgs[@]}; i++)); do
            repodepspkgsver="${repodepspkgsver}${repodepspkgs[$i]}-${repodepsSver[$i]}  "
        done
        printf "\n${colorY}%-17s${reset} %s\n" $"AUR Packages  (${#deps[@]}):" "$depsver"
        [[ -n "${repodepspkgs[@]}" ]] && printf "${colorY}%-17s${reset} %s\n" $"Repo Packages (${#repodepspkgs[@]}):" "$repodepspkgsver"
    fi

    if [[ -n "${repodepspkgs[@]}" ]]; then
        strrepodlsize=$"Repo Download Size:"; strrepoinsize=$"Repo Installed Size:"; strsumk=$"$sumk MiB"; strsumm=$"$summ MiB"
        lreposizelabel=$(getlength "$strrepodlsize" "$strrepoinsize")
        lreposize=$(getlength "$strsumk" "$strsumm")
        printf "\n${colorW}%-${lreposizelabel}s${reset}  %${lreposize}s\n" "$strrepodlsize" "$strsumk"
        printf "${colorW}%-${lreposizelabel}s${reset}  %${lreposize}s\n" "$strrepoinsize" "$strsumm"
    fi

    echo
    if [[ ! $noconfirm ]]; then
        [[ $installpkg ]] && action=$"installation" || action=$"download"
        if ! proceed "y" $"Proceed with $action?"; then
            exit
        fi
    fi
}

DownloadPkgs() {
    # download and extract
    note "i" $"${colorW}Retrieving package(s)...${reset}"
    coweropts+=("-d") && DownloadAur ${deps[@]}

    getpackagebase ${deps[@]}
    EditPkgs ${basepkgs[@]}
}

EditPkgs() {
    [[ $noedit ]] && return
    for i in "$@"; do
        [[ " ${cachedpkgs[@]} " =~ " $i " ]] && continue
        getinstallscripts $i
        if [[ ! $edit ]]; then
            # edit pkgbuild
            if [[ ! $editpkgbuild = false ]]; then
                if proceed "y" $"View $i PKGBUILD?"; then
                    [[ -e "$builddir/$i/PKGBUILD" ]] && $editor "$builddir/$i/PKGBUILD" && note "s" $"${colorW}$i${reset} PKGBUILD viewed" || note "e" $"Could not open ${colorW}$i${reset} PKGBUILD"
                fi
            fi
            # edit install script
            if [[ ! $editinstall = false && -n "${installscripts[@]}" ]]; then
                for j in "${installscripts[@]}"; do
                if proceed "y" $"View $j script?"; then
                        [[ -e "$builddir/$i/$j" ]] && $editor "$builddir/$i/$j" && note "s" $"${colorW}$j${reset} script viewed" || note "e" $"Could not open ${colorW}$j${reset} script"
                fi
                done
            fi
        else
            [[ -e "$builddir/$i/PKGBUILD" ]] && $editor "$builddir/$i/PKGBUILD" && note "s" $"${colorW}$i${reset} PKGBUILD viewed" || note "e" $"Could not open ${colorW}$i${reset} PKGBUILD"
            if [[ -n "${installscripts[@]}" ]]; then
                for j in "${installscripts[@]}"; do
                    [[ -e "$builddir/$i/$j" ]] && $editor "$builddir/$i/$j" && note "s" $"${colorW}$j${reset} script viewed" || note "e" $"Could not open ${colorW}$j${reset} script"
                done
            fi
        fi
    done
}

MakePkgs() {
    # current orphan packages
    oldorphanpkgs=($($pacmanbin -Qdtq))

    # initialize sudo
    if sudo -v; then
        [[ $sudoloop = true ]] && sudov &
    fi

    # split packages support
    for ((i=0; i<${#pkgsbase[@]}; i++)); do
        for ((j=0; j<${#deps[@]}; j++)); do
            [[ "${pkgsbase[$i]}" = "${pkgsbase[$j]}" ]] && [[ ! " ${pkgsdeps[@]} " =~ " ${deps[$j]} " ]] && pkgsdeps+=(${deps[$j]})
        done
        pkgsdeps+=("#")
    done
    pkgsdeps=($(sed 's/ # /\n/g' <<< ${pkgsdeps[@]} | tr -d '#' | sed '/^ $/d' | tr ' ' ',' | sed 's/^,//g;s/,$//g'))

    # reverse deps order
    basepkgs=($(awk '{for (i=NF;i>=1;i--) print $i}' <<< ${basepkgs[@]} | awk -F "\n" '{print}'))
    pkgsdeps=($(awk '{for (i=NF;i>=1;i--) print $i}' <<< ${pkgsdeps[@]} | awk -F "\n" '{print}'))

    # integrity check
    for ((i=0; i<${#basepkgs[@]}; i++)); do
        # get splitted packages list
        pkgsdepslist=($(awk -F "," '{for (k=1;k<=NF;k++) print $k}' <<< ${pkgsdeps[$i]}))

        # cache check
        unset cachedpkg
        if [[ -z "$(grep -E "\-(bzr|git|hg|svn)$" <<< ${basepkgs[$i]})" ]]; then
            for j in "${pkgsdepslist[@]}"; do
                depsAver="$(getjsonvarvar "Version" "$j")"
                [[ $PKGDEST && ! $rebuild ]] && getcachedpkg "$j-$depsAver" "$PKGDEST"
            done
        # install vcs client
        else
            vcspkg=$(awk -F "-" '{print $NF}' <<< ${basepkgs[$i]})
            for j in "${VCSCLIENTS[@]}"; do
                if [[ ! "${vcschecked[@]}" =~ "$vcspkg" && $(awk -F "::" '{print $1}' <<< $j) == "$vcspkg" ]]; then
                    vcsclient=$(awk -F "::" '{print $NF}' <<< $j) && vcschecked+=($vcspkg)
                    [[ -z "$(expac -Qs '%n' "^$vcsclient$")" ]] && yes $(gettext pacman Y) | sudo $pacmanbin -S $vcsclient --asdeps
                fi
            done
        fi

        if [[ ! $cachedpkg || $rebuild ]]; then
            cd "$builddir/${basepkgs[$i]}"
            note "i" $"Checking ${colorW}${pkgsdeps[$i]}${reset} integrity..."
            if [[ $silent ]]; then
                makepkg -f --verifysource ${makeopts[@]} &>/dev/null
            else
                makepkg -f --verifysource ${makeopts[@]}
            fi
            (( $? > 0)) && errmakepkg+=(${pkgsdeps[$i]})
            # silent extraction and pkgver update only
            makepkg -od --noprepare --skipinteg ${makeopts[@]} &>/dev/null
        fi
    done
    for i in "${errmakepkg[@]}"; do
        note "f" $"failed to verify ${colorW}$i${reset} integrity"
    done
    [[ -n "${errmakepkg[@]}" ]] && exit 1

    # set lock
    [[ -e "$tmpdir/build.lck" ]] && note "e" $"build.lck exists in $tmpdir" && exit 1
    touch "$tmpdir/build.lck"

    # install provider packages
    if [[ -n "${providerpkgs[@]}" ]]; then
        note "i" $"Installing ${colorW}${providerpkgs[@]}${reset} dependencies..."
        yes $(gettext pacman Y) | sudo $pacmanbin -S ${providerpkgs[@]} --asdeps
    fi

    # main
    for ((i=0; i<${#basepkgs[@]}; i++)); do

        # get splitted packages list
        pkgsdepslist=($(awk -F "," '{for (k=1;k<=NF;k++) print $k}' <<< ${pkgsdeps[$i]}))

        cd "$builddir/${basepkgs[$i]}"

        # build devel if necessary only (supported protocols only)
        unset aurdevelpkgsAall
        if [[ -n "$(grep -E "\-(bzr|git|hg|svn)$" <<< ${basepkgs[$i]})" && ! $rebuild ]]; then
            if [[ -n "$(grep -E '^pkgver[ ]*[(]+[)]+' "PKGBUILD")" ]]; then
                aurdevelpkgsAver=$(grep '^pkgver=' "PKGBUILD" | cut -d '=' -f 2- | tr -d "'\"")
                aurdevelpkgsArel=$(grep '^pkgrel=' "PKGBUILD" | cut -d '=' -f 2- | tr -d "'\"")
                aurdevelpkgsAepo=$(grep '^epoch=' "PKGBUILD" | cut -d '=' -f 2- | tr -d "'\"")
                if [[ -n "$aurdevelpkgsAepo" ]]; then
                    aurdevelpkgsAall="$aurdevelpkgsAepo:$aurdevelpkgsAver-$aurdevelpkgsArel"
                else
                    aurdevelpkgsAall="$aurdevelpkgsAver-$aurdevelpkgsArel"
                fi

                # check split packages update
                unset basepkgsupdate checkpkgsdepslist
                for j in "${pkgsdepslist[@]}"; do
                    aurdevelpkgsQver=$(expac -Qs '%v' "^$j$")
                    if [[ -n $aurdevelpkgsQver && $(vercmp "$aurdevelpkgsQver" "$aurdevelpkgsAall") -ge 0 ]] && [[ $needed ]]; then
                        note "w" $"${colorW}$j${reset} is up-to-date -- skipping"
                        continue
                    else
                        basepkgsupdate='true'
                        checkpkgsdepslist+=($j)
                    fi
                done
                if [[ $basepkgsupdate ]]; then
                    pkgsdepslist=(${checkpkgsdepslist[@]})
                else
                    continue
                fi
            fi
        fi

        # check package cache
        for j in "${pkgsdepslist[@]}"; do
            unset cachedpkg
            [[ $aurdevelpkgsAall ]] && depsAver="$aurdevelpkgsAall" || depsAver="$(getjsonvarvar "Version" "$j")"
            [[ $PKGDEST && ! $rebuild ]] && getcachedpkg "$j-$depsAver" "$PKGDEST"
            if [[ $cachedpkg ]]; then
                if [[ " ${aurdepspkgs[@]} " =~ " $j " || $installpkg ]]; then
                    note "i" $"Installing ${colorW}$j${reset} cached package..."
                    yes $(gettext pacman Y) | sudo $pacmanbin -U $cachedpkg ${pacopts[@]}
                    [[ ! " ${aurpkgs[@]} " =~ " $j " ]] && sudo $pacmanbin -D $j --asdeps ${pacopts[@]} &>/dev/null
                else
                    note "w" $"Package ${colorW}$j${reset} already available in cache"
                fi
                pkgsdeps=($(tr ' ' '\n' <<< ${pkgsdeps[@]} | sed "s/^$j,//g;s/,$j$//g;s/,$j,/,/g;s/^$j$/#/g"))
                continue
            fi
        done
        [[ "${pkgsdeps[$i]}" = '#' ]] && continue

        # build
        note "i" $"Building ${colorW}${pkgsdeps[$i]}${reset} package(s)..."

        if [[ $installpkg ]]; then
            # install
            if [[ $silent ]]; then
                yes $(gettext pacman Y) | makepkg -sfi ${makeopts[@]} --pkg ${pkgsdeps[$i]} &>/dev/null
            else
                yes $(gettext pacman Y) | makepkg -sfi ${makeopts[@]} --pkg ${pkgsdeps[$i]}
            fi
        else
            unset isaurdeps
            for j in "${pkgsdepslist[@]}"; do
                [[ " ${aurdepspkgs[@]} " =~ " $j " ]] && isaurdeps=true
            done
            if [[ $isaurdeps = true ]]; then
                # install AUR deps
                note "i" $"Installing ${colorW}${pkgsdeps[$i]}${reset} dependencies..."
                if [[ $silent ]]; then
                    yes $(gettext pacman Y) | makepkg -sfi ${makeopts[@]} --pkg ${pkgsdeps[$i]} &>/dev/null
                else
                    yes $(gettext pacman Y) | makepkg -sfi ${makeopts[@]} --pkg ${pkgsdeps[$i]}
                fi
            else
                # install then remove binary deps
                if [[ $silent ]]; then
                    yes $(gettext pacman Y) | makepkg -sfr ${makeopts[@]} --pkg ${pkgsdeps[$i]} &>/dev/null
                else
                    yes $(gettext pacman Y) | makepkg -sfr ${makeopts[@]} --pkg ${pkgsdeps[$i]}
                fi
            fi
        fi
        # clean
        if (( $? > 0)); then
            errmakepkg+=(${pkgsdeps[$i]})
            note "w" $"${colorW}${basepkgs[$i]}${reset} cleaning skipped"
            [[ $silent ]] && note "f" $"check build log in ${colorW}$builddir/${basepkgs[$i]}${reset}"
        else
            if [[ ! $installpkg && ! $PKGDEST ]]; then
                note "w" $"${colorW}${basepkgs[$i]}${reset} cleaning skipped"
            else
                CleanUp ${basepkgs[$i]}
            fi
        fi

        # set dep status
        if [[ $installpkg ]]; then
            for j in "${pkgsdepslist[@]}"; do
                [[ ! " ${aurpkgs[@]} " =~ " $j " ]] && sudo $pacmanbin -D $j --asdeps ${pacopts[@]} &>/dev/null
                [[ " ${pacopts[@]} " =~ " --asdeps " ]] && sudo $pacmanbin -D $j --asdeps ${pacopts[@]} &>/dev/null
                [[ " ${pacopts[@]} " =~ " --asexplicit " ]] && sudo $pacmanbin -D $j --asexplicit ${pacopts[@]} &>/dev/null
            done
        fi
    done

    # remove AUR deps
    if [[ ! $installpkg && -n "${aurdepspkgs[@]}" ]]; then
        aurdepspkgs=($(expac -Q '%n' "${aurdepspkgs[@]}"))
        if [[ -n "${aurdepspkgs[@]}" ]]; then
            note "i" $"Removing installed AUR dependencies..."
            sudo $pacmanbin -Rsn ${aurdepspkgs[@]} --noconfirm
        fi
        # readd removed conflicting packages
        [[ -n "${aurconflictingpkgsrm[@]}" ]] && sudo $pacmanbin -S ${aurconflictingpkgsrm[@]} --asdeps --needed --noconfirm
        [[ -n "${repoconflictingpkgsrm[@]}" ]] && sudo $pacmanbin -S ${repoconflictingpkgsrm[@]} --asdeps --needed --noconfirm
    fi

    # remove locks
    [[ -e "$tmpdir/sudov.lck" ]] && rm "$tmpdir/sudov.lck"
    rm "$tmpdir/build.lck"

    # new orphan packages check
    orphanpkgs=($($pacmanbin -Qdtq))
    neworphanpkgs=($(LC_COLLATE=C comm -23 <(tr ' ' '\n' <<< ${orphanpkgs[@]} | LC_COLLATE=C sort -u) <(tr ' ' '\n' <<< ${oldorphanpkgs[@]} | LC_COLLATE=C sort -u)))
    for i in "${neworphanpkgs[@]}"; do
        note "w" $"${colorW}$i${reset} is a ${colorY}new orphan${reset} package"
    done

    # makepkg failure check
    for i in "${errmakepkg[@]}"; do
        note "f" $"failed to build ${colorW}$i${reset} package(s)"
    done

    # exit error code
    [[ -z "${errmakepkg[@]}" ]] && exit
}

CleanUp() {
    [[ ! $clean = true ]] && return
    local i
    if [[ -n "$@" ]]; then
        cd "$builddir"
        for i in "$@"; do
            # skip devel (no nightly here)
            if [[ ! $cleandevel = true && -n "$(grep -E "\-(cvs|svn|git|hg|bzr|darcs)$" <<< $i)" && $count -lt 2 ]]; then
                note "w" $"${colorW}$i${reset} cleaning skipped"
                continue
            else
                # hack for vcs protected files
                chmod -R 755 $i &>/dev/null
                rm -r $i &>/dev/null && note "s" $"${colorW}$i${reset} cleaned" || note "w" $"Could not clean ${colorW}$i${reset}"
            fi
        done
    else
        # hack for vcs protected files
        chmod -R 755 "${builddir:?}/*" &>/dev/null
        rm -r "${builddir:?}/*" &>/dev/null && note "s" $"Build directory cleaned" || note "w" $"Build directory already cleaned"
    fi
}

DownloadAur() {
    [[ $color != 'never' ]] && coweropts=(${coweropts[@]/auto/always})
    while read -r flag pkg info; do
        case $flag in
            S)  [[ $operation = download && -n "$info" ]] && echo "$info" && pkgsedit+=($pkg);;
            W)  [[ $operation = download && -n "$info" ]] && echo "$info";;
            E)  [[ -n "$info" ]] && echo "$info";;
        esac
    done < <(cower ${coweropts[@]} -b $@ ${ignoreopts[@]} -t $builddir 2>&1)
    wait
}

SearchInfoAur() {
    [[ $sortbyvotes = true && -z "$(grep -E "\-\-[r]?sort" <<< ${coweropts[@]})" ]] && coweropts+=("--rsort=votes")
    cower ${coweropts[@]} $@
}

CheckRepo() {
    getignoredpkgs
    repopkgsQood=($($pacmanbin -Quq $@))
    if [[ -n "${repopkgsQood[@]}" ]]; then
        [[ $quiet ]] && tr ' ' '\n' <<< ${repopkgsQood[@]} && return
        repopkgsQver=($(expac -Q '%v' "${repopkgsQood[@]}"))
        repopkgsSver=($(expac -S -1 '%v' "${repopkgsQood[@]}"))
        repopkgsSrepo=($(expac -S -1 '%r' "${repopkgsQood[@]}"))
        repopkgsQgrp=($(expac -Qv -l "#" '(%G)' "${repopkgsQood[@]}"))
        for ((i=0; i<${#repopkgsQood[@]}; i++)); do
            [[ "${repopkgsQgrp[$i]}" = '(None)' ]] && unset repopkgsQgrp[$i] || repopkgsQgrp[$i]=$(tr '#' ' ' <<< ${repopkgsQgrp[$i]})
            [[ " ${ignoredpkgs[@]} " =~ " ${repopkgsQood[$i]} " ]] && repopkgsQignore[$i]=$"[ ignored ]"
        done
        lname=$(getlength "${repopkgsQood[@]}")
        lQver=$(getlength "${repopkgsQver[@]}")
        lSver=$(getlength "${repopkgsSver[@]}")
        lrepo=$(getlength "${repopkgsSrepo[@]}")
        lgrp=$(getlength "${repopkgsQgrp[@]}")
        for ((i=0; i<${#repopkgsQood[@]}; i++)); do
            printf "${colorB}::${reset} ${colorM}%-${lrepo}s${reset}  ${colorW}%-${lname}s${reset}  ${colorR}%-${lQver}s${reset}  ->  ${colorG}%-${lSver}s${reset}  ${colorB}%-${lgrp}s${reset}  ${colorY}%s${reset}\n" "${repopkgsSrepo[$i]}" "${repopkgsQood[$i]}" "${repopkgsQver[$i]}" "${repopkgsSver[$i]}" "${repopkgsQgrp[$i]}" "${repopkgsQignore[$i]}"
        done
    fi
}

CheckAur() {
    getignoredpkgs
    aurpkgsQood=($(cower ${coweropts[@]} $@ | sed -r "s:\x1B\[[0-9;]*[mK]::g"))
    if [[ -n "${aurpkgsQood[@]}" ]]; then
        [[ $quiet ]] && tr ' ' '\n' <<< ${aurpkgsQood[@]} && return
        downloadjson ${aurpkgsQood[@]}
        aurpkgsAname=($(getjsonvar "Name"))    # return sorted results
        aurpkgsAver=($(getjsonvar "Version"))
        aurpkgsQver=($(expac -Q '%v' "${aurpkgsAname[@]}"))
        for ((i=0; i<${#aurpkgsQood[@]}; i++)); do
            [[ " ${ignoredpkgs[@]} " =~ " ${aurpkgsQood[$i]} " ]] && aurpkgsQignore[$i]=$"[ ignored ]"
        done
        [[ ! $lname ]] && lname=$(getlength "${aurpkgsAname[@]}")
        [[ ! $lQver ]] && lQver=$(getlength "${aurpkgsQver[@]}")
        [[ ! $lSver ]] && lSver=$(getlength "${aurpkgsAver[@]}")
        [[ ! $lrepo ]] && lrepo=3
        for ((i=0; i<${#aurpkgsAname[@]}; i++)); do
            printf "${colorB}::${reset} ${colorM}%-${lrepo}s${reset}  ${colorW}%-${lname}s${reset}  ${colorR}%-${lQver}s${reset}  ->  ${colorG}%-${lSver}s${reset}  ${colorB}%-${lgrp}s${reset}  ${colorY}%s${reset}\n" "aur" "${aurpkgsAname[$i]}" "${aurpkgsQver[$i]}" "${aurpkgsAver[$i]}" " " "${aurpkgsQignore[$i]}"
        done
    fi
}

CleanCache() {
    if [[ $PKGDEST && $PKGDEST != '/var/cache/pacman/pkg/' ]]; then
        [[ ! $aur ]] && echo
        printf "%s %s\n" $"AUR cache directory:" "$PKGDEST"
        if [[ $count -eq 1 ]]; then
            printf "${colorW}%s${reset}\n %s\n" $"Packages to keep:" $"All locally installed packages"
            if ! proceed "y" $"Do you want to remove all other packages from AUR cache?"; then
                exit
            fi
            printf "%s\n" $"removing old packages from cache..."
            paccache -ru -k0 -c $PKGDEST &>/dev/null
        else
            if ! proceed "n" $"Do you want to remove ALL files from AUR cache?"; then
                printf "%s\n" $"removing all files from AUR cache..."
                paccache -r -k0 -c $PKGDEST &>/dev/null
            fi
        fi
    fi
}

getignoredpkgs() {
    ignoredpkgs+=($(grep '^IgnorePkg' '/etc/pacman.conf' | cut -d '=' -f 2- | tr -d "'\""))
    [[ -e "$HOME/.config/cower/config" ]] && ignoredpkgs+=($(grep '^IgnorePkg' "$HOME/.config/cower/config" | cut -d '=' -f 2- | tr -d "'\""))
    ignoredpkgs=(${ignoredpkgs[@]//,/ })
}

getinstallscripts() {
    [[ ! -d "$builddir/$1" ]] && return
    unset installscriptspath installscripts
    installscriptspath=($(find "$builddir/$1/" -maxdepth 1 -name "*.install"))
    [[ -n "${installscriptspath[@]}" ]] && installscripts=($(basename -a ${installscriptspath[@]}))
}

getcachedpkg() {
    cachedpkg="$2/$1-${CARCH}${PKGEXT}"
    [[ ! -f "$cachedpkg" ]] && cachedpkg="$2/$1-any${PKGEXT}"
    [[ ! -f "$cachedpkg" ]] && unset cachedpkg
}

getpackagebase() {
    for i in "$@"; do
        pkgsbase+=($(getjsonvarvar "PackageBase" "$i"))
    done
    for i in "${pkgsbase[@]}"; do
        [[ " ${basepkgs[@]} " =~ " $i " ]] && continue
        basepkgs+=($i)
    done
}

downloadjson() {
    aururl="https://aur.archlinux.org/rpc.php?type=multiinfo&v=3"
    urlencodedpkgs=($(sed 's/+/%2b/g;s/@/%40/g' <<< $@)) # pkgname consists of alphanum@._+-
    urlargs="$(printf "&arg[]=%s" "${urlencodedpkgs[@]}")"
    # ensure the URI length is shorter than 8190 bytes (52 for AUR path, 13 reserved)
    if [[ "${#urlargs}" -lt 8125 ]]; then
        curl -sfg --compressed -C 0 "$aururl$urlargs" -o "$tmpdir/rpc.json" || note "e" $"Could not connect to the AUR"
    else
        urlpkgs=($@)
        urlencodedpkgs1=($(sed 's/+/%2b/g;s/@/%40/g' <<< ${urlpkgs[@]:0:$((${#urlpkgs[@]}/2))}))
        urlencodedpkgs2=($(sed 's/+/%2b/g;s/@/%40/g' <<< ${urlpkgs[@]:$((${#urlpkgs[@]}/2))}))
        urlargs1="$(printf "&arg[]=%s" "${urlencodedpkgs1[@]}")"
        urlargs2="$(printf "&arg[]=%s" "${urlencodedpkgs2[@]}")"
        curl -sfg --compressed -C 0 "$aururl$urlargs1" -o "$tmpdir/rpc1.json" "$aururl$urlargs2" -o "$tmpdir/rpc2.json" || note "e" $"Could not connect to the AUR"
        # merge json files
        json_reformat < "$tmpdir/rpc1.json" | head -n -2 | sed -r 's/}$/},/g;s/"resultcount": [0-9]+/"resultcount": "?"/g' > "$tmpdir/rpc.json"
        json_reformat < "$tmpdir/rpc2.json" | tail -n +6 >> "$tmpdir/rpc.json"
    fi
}

getjsonvar() {
    json_reformat < "$tmpdir/rpc.json" | tr -d "\", " | grep -Po "$1:.*" | sed -r "s/$1:/$1#/g" | awk -F "#" '{print $2}'
}

getjsonvarvar() {
    json_reformat < "$tmpdir/rpc.json" | tr -d ", " | sed -e "/\"Name\":\"$2\"/,/}/!d" | tr -d "\"" | grep -Po "$1:.*" | sed -r "s/$1:/$1#/g" | awk -F "#" '{print $2}'
}

getjsonarray() {
    json_reformat < "$tmpdir/rpc.json" | tr -d ", " | sed -e "/^\"$1\"/,/]/!d" | tr -d '\"' | tr '\n' ' ' | sed "s/] /]\n/g" | awk -F ":" '{print $2}' | tr -d '[]"' | tr -d '\n'
}

getjsonarrayvar() {
    json_reformat < "$tmpdir/rpc.json" | tr -d ", " | sed -e "/\"Name\":\"$2\"/,/}/!d" | sed -e "/^\"$1\"/,/]/!d" | tr -d '\"' | tr '\n' ' ' | awk -F ":" '{print $2}' | tr -d '[]'
}

checkQrequires() {
    Qrequires=$(expac -Q '%n %D' | grep -E " $@[\+]*[^a-zA-Z0-9_@\.\+-]+" | awk -F " " '{print $1}' | tr '\n' ' ')
    if [[ -n "${Qrequires[@]}" ]]; then
        note "f" $"failed to prepare transaction (could not satisfy dependencies)"
        note "e" $"${Qrequires[@]}: requires $@"
    fi
}

proceed() {
    Y="$(gettext pacman Y)"; y="${Y,,}";
    N="$(gettext pacman N)"; n="${N,,}"
    case "$1" in
        y)  printf "${colorB}%s${reset} ${colorW}%s${reset}" "::" $"$2 [Y/n] "
            read -n 1 answer
            echo
            case $answer in
                $Y|$y|'') return 0;;
                *) return 1;;
            esac;;
        n)  printf "${colorB}%s${reset} ${colorW}%s${reset}" "::" $"$2 [y/N] "
            read -n 1 answer
            echo
            case $answer in
                $N|$n|'') return 0;;
                *) return 1;;
            esac;;
    esac
}

note() {
    case "$1" in
        i) echo -e "${colorB}::${reset} $2";;   # info
        s) echo -e "${colorG}::${reset} $2";;   # success
        w) echo -e "${colorY}::${reset} $2";;   # warn
        f) echo -e "${colorR}::${reset} $2";;   # fail
        e) echo -e "${colorR}::${reset} $2";    # error
           exit 1;;
    esac
}

getlength() {
    local length=0
    for i in "$@"; do
        x=${#i}
        [[ $x -gt $length ]] && length=$x
    done
    echo $length
}

nothingtodo() {
    [[ -z "$@" ]] && printf "%s\n" $" there is nothing to do" && exit || return 0
}

sudov() {
    touch "$tmpdir/sudov.lck"
    while [[ -e "$tmpdir/sudov.lck" ]]; do
        sudo -n -v
        sleep 2
    done
}

trap ctrlc INT
ctrlc() {
    echo
    [[ -e "$tmpdir/sudov.lck" ]] && rm "$tmpdir/sudov.lck"
    [[ -e "$tmpdir/build.lck" ]] && rm "$tmpdir/build.lck"
    [[ $operation = sync ]] && [[ ! $search && ! $info ]] && [[ -n "${basepkgs[@]}" ]] && CleanUp ${basepkgs[@]}
    exit
}

usage() {
    printf "%s\n" $"usage:  pacaur <operation> [options] [target(s)]"
    printf "%s\n" $"operations:"
    printf "%s\n" $" pacman extension"
    printf "%s\n" $"   -S, -Q           extend pacman operations to the AUR"
    printf "%s\n" $" AUR only"
    printf "%s\n" $"   -s, --search     search AUR for matching strings"
    printf "%s\n" $"   -i, --info       view package information"
    printf "%s\n" $"   -d, --download   download target(s) -- pass twice to download AUR dependencies"
    printf "%s\n" $"   -m, --makepkg    download and make target(s)"
    printf "%s\n" $"   -y, --sync       download, make and install target(s)"
    printf "%s\n" $"   -k, --check      check for AUR update(s)"
    printf "%s\n" $"   -u, --update     update AUR package(s)"
    printf "%s\n" $" general"
    printf "%s\n" $"   -v, --version    display version information"
    printf "%s\n" $"   -h, --help       display help information"
    echo
    printf "%s\n" $"options:"
    printf "%s\n" $" pacman extension - can be used with the -S, -Ss, -Si, -Sii, -Sw, -Su, -Qu, -Sc, -Scc operations"
    printf "%s\n" $"   -a, --aur        only search, install or clean target(s) from the AUR"
    printf "%s\n" $"   -r, --repo       only search, install or clean target(s) from the repositories"
    printf "%s\n" $" general"
    printf "%s\n" $"   -e, --edit       edit target(s) PKGBUILD and view install script"
    printf "%s\n" $"   -c, --clean      clean target(s) build files -- can be combined with the -m, -y, -u operations"
    printf "%s\n" $"   -q, --quiet      show less information for query and search"
    printf "%s\n" $"   --devel          consider AUR development packages upgrade"
    printf "%s\n" $"   --ignore         ignore a package upgrade (can be used more than once)"
    printf "%s\n" $"   --needed         do not reinstall already up to date target(s)"
    printf "%s\n" $"   --noconfirm      do not prompt for any confirmation"
    printf "%s\n" $"   --noedit         do not prompt to edit files"
    printf "%s\n" $"   --rebuild        always rebuild package(s)"
    echo
}

version() {
    echo "pacaur $version"
}

#
# Main
#

# get short arguments
args=($@)
for i in "${args[@]}"; do
    [[ "$i" =~ ^-[a-zA-Z0-9] ]] && opts+=($i)
done

# get options
count=0
while [[ -n "${!OPTIND}" ]]; do
    while getopts "sidmykufecqrahvVDQRSTUbglnoptw-:" OPT; do
        pacmanarg+=("-$OPT");
        case "$OPT" in
            -)
                case "$OPTARG" in
                    search) operation=sync; search=true; coweropts+=("-s"); aur='1';;
                    info) operation=sync; info=true; coweropts+=("-i"); aur='1';;
                    download) operation=download; coweropts+=("-d");;
                    makepkg) operation=sync; coweropts+=("-f"); aur='1';;
                    sync) operation=sync; installpkg=true; coweropts+=("-f"); aur='1';;
                    check) operation=upgrades; coweropts+=("-uq"); aur='1';;
                    update) operation=sync; upgrade=true; installpkg=true; coweropts+=("-f"); selective=true; aur='1';;
                    force) coweropts+=("-f"); pacopts+=("--force");;
                    edit) edit=true; [[ ! $pacQ && ! $operation ]] && operation=editpkg;;
                    clean) operation=cleanpkg; clean=true; ((count++));;
                    quiet) quiet=true; pacopts+=("--quiet"); coweropts+=("-q"); color=never;;
                    repo) repo='1';;
                    aur) aur='1';;
                    devel) devel=true;;
                    ignore) ignoredpkgs+=(${!OPTIND}); ignoreopts+=("--ignore ${!OPTIND}"); shift;;
                    color) color=${!OPTIND}; pacopts+=("--color ${!OPTIND}") && coweropts+=("--color=${!OPTIND}"); shift;;
                    ignore-ood) coweropts+=("--ignore-ood");;
                    no-ignore-ood) coweropts+=("--no-ignore-ood");;
                    asort) coweropts+=("--sort=name");;
                    vsort) coweropts+=("--rsort=votes");;
                    asdep|asdeps) pacopts+=("--asdeps"); makeopts+=("--asdeps");;
                    needed) needed=true; pacopts+=("--needed"); makeopts+=("--needed");;
                    nodeps) nodeps=true; pacopts+=("--nodeps"); makeopts+=("--nodeps"); ((count++));;
                    noconfirm) noconfirm=true; pacopts+=("--noconfirm");;
                    noedit) noedit=true;;
                    rebuild) rebuild=true;;
                    root) root=true;;
                    silent) silent=true; makeopts+=("--log");;
                    version) version; exit;;
                    help) usage; exit;;
                    *) pacopts+=("--$OPTARG");;
                esac;;
            s)  [[ $pacS ]] && operation=sync && search=true && coweropts+=("-s");
                [[ $pac || $pacQ || $pacS ]] && continue || operation=sync; search=true; coweropts+=("-s"); aur='1';;
            i)  [[ $pacS ]] && operation=sync && info=true && coweropts+=("-i");
                [[ $pac || $pacQ || $pacS ]] && continue || operation=sync; info=true; coweropts+=("-i"); aur='1';;
            d)  [[ $pacS ]] && nodeps=true && pacopts+=("--nodeps") && makeopts+=("--nodeps") && ((count++));
                [[ $pac || $pacQ || $pacS ]] && continue || operation=download; coweropts+=("-d");;
            m)  [[ $pac || $pacQ || $pacS ]] && continue || operation=sync; coweropts+=("-f"); aur='1';;
            y)  [[ $pacS ]] && operation=sync && refresh=true;
                [[ $pac || $pacQ || $pacS ]] && continue || operation=sync; installpkg=true; coweropts+=("-f"); aur='1';;
            k)  [[ $pac || $pacQ || $pacS ]] && continue || operation=upgrades; coweropts+=("-uq"); aur='1';;
            u)  [[ $pacQ ]] && operation=upgrades && coweropts+=("-uq");
                [[ $pacS ]] && operation=sync && upgrade=true && coweropts+=("-f");
                [[ $pac || $pacQ || $pacS ]] && continue || operation=sync; upgrade=true; installpkg=true; coweropts+=("-f"); selective=true; aur='1';;
            f)  [[ $pac || $pacQ || $pacS ]] && continue || coweropts+=("-f");;
            e)  [[ $pacQ ]] && pacopts+=("--explicit") && continue || edit=true;
                [[ ! $operation ]] && operation=editpkg;;
            c)  [[ $pacS ]] && operation=sync && cleancache=true && ((count++));
                [[ $pac || $pacQ || $pacS ]] && continue || [[ ! $operation ]] && operation=cleanpkg; clean=true && ((count++));;
            q)  quiet=true; pacopts+=("--quiet"); coweropts+=("-q"); color=never;;
            r)  repo='1';;
            a)  aur='1';;
            Q)  pacQ='1';;
            S)  pacS='1'; operation=sync; coweropts+=("-f");
                [[ "${opts[@]}" =~ "w" ]] && continue || installpkg=true;
                [[ "${opts[@]}" =~ "g" || "${opts[@]}" =~ "l" || "${opts[@]}" =~ "p" ]] && unset operation;;
            [A-Z]) pac='1';;
            h)  [[ "${opts[@]}" =~ ^-[A-Z] ]] && unset operation && continue || usage; exit;;
            v)  [[ "${opts[@]}" =~ ^-[A-Z] ]] && continue || version; exit;;
            *)  continue;;
        esac
    done
    # packages
    [[ -z "${!OPTIND}" ]] && break || pkgs+=(${!OPTIND})
    shift $OPTIND
    OPTIND=1
done

# color
if [[ -n "$(grep '^Color' '/etc/pacman.conf')" && $color != 'never' ]]; then
    [[ $color = 'always' ]] && coweropts+=("--color=always") || coweropts+=("--color=auto")
    reset="\e[0m"
    colorR="\e[1;31m"
    colorG="\e[1;32m"
    colorY="\e[1;33m"
    colorB="\e[1;34m"
    colorM="\e[1;35m"
    colorW="\e[1;39m"
elif [[ -z "$(grep '^Color' '/etc/pacman.conf')" && ($color = 'always' || $color = 'auto') ]]; then
    pacopts+=("--color $color") && coweropts+=("--color=$color")
    reset="\e[0m"
    colorR="\e[1;31m"
    colorG="\e[1;32m"
    colorY="\e[1;33m"
    colorB="\e[1;34m"
    colorM="\e[1;35m"
    colorW="\e[1;39m"
else
    [[ $color != 'always' && $color != 'auto' ]] && makeopts+=("--nocolor")
fi

# sanity check
pacmanarg=(${pacmanarg[@]/--/})
pacmanarg=(${pacmanarg[@]/-r/})
pacmanarg=(${pacmanarg[@]/-a/})
[[ $operation = sync && ! $search && ! $info && ! $cleancache ]] && [[ "$EUID" -eq 0 ]] && note "e" $"you cannot perform this operation as root"
[[ $pacS ]] && pacmanarg=(${pacmanarg[@]/-e/})
[[ $pacS ]] && [[ $search && $info ]] && coweropts=(${coweropts[@]/-i/})
[[ $pacS ]] && [[ $cleancache ]] && unset search info upgrade
[[ ! $editor ]] && [[ ! -f /usr/bin/vi ]] && note "e" $"${colorW}editor${reset} variable unset"
[[ ! -w "$builddir" ]] && note "e" $"${colorW}$builddir${reset} does not have write permission."
[[ -z "${pkgs[@]}" ]] && [[ $operation = download || $operation = sync || $operation = editpkg || ($operation = cleanpkg && $count -eq 1) ]] && [[ ! $refresh && ! $upgrade && ! $cleancache ]] && note "e" $"no targets specified (use -h for help)"
[[ $repo && $aur ]] && note "e" $"target not found"
[[ $root ]] && note "e" $"alternative installation root option not supported"

# operations
case $operation in
    download)
        # download (-d) handling
        DownloadAur ${pkgs[@]}
        downloadjson ${pkgsedit[@]}
        getpackagebase ${pkgsedit[@]}
        EditPkgs ${pkgsbase[@]}
        exit;;
    cleanpkg)
        # clean (-c) handling
        CleanUp ${pkgs[@]}
        exit;;
    editpkg)
        # edit (-e) handling
        downloadjson ${pkgs[@]}
        getpackagebase ${pkgs[@]}
        EditPkgs ${pkgsbase[@]}
        exit;;
    sync)
        # search (-Ss, -s) handling
        if [[ $search ]]; then
            if [[ ! $aur ]]; then
                [[ $refresh ]] && sudo $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${pkgs[@]}
                [[ ! $refresh ]] && $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${pkgs[@]}
            fi
            [[ ! $repo ]] && [[ $fallback = true || $aur ]] && SearchInfoAur ${pkgs[@]}
        # info (-Si, -i) handling
        elif [[ $info ]]; then
            [[ -z "${pkgs[@]}" ]] && $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} || ClassifyPkgs ${pkgs[@]}
            if [[ -n "${repopkgs[@]}" ]]; then
                [[ $refresh ]] && sudo $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
                [[ ! $refresh ]] && $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
            fi
            if [[ -n "${aurpkgs[@]}" ]]; then
                [[ $refresh ]] && [[ -z "${repopkgs[@]}" ]] && sudo $pacmanbin -Sy ${pacopts[@]} ${ignoreopts[@]}
                [[ $fallback = true && ! $aur ]] && note "w" $"Package(s) ${colorW}${aurpkgs[*]}${reset} not found in repositories, trying ${colorM}AUR${reset}..."
                SearchInfoAur ${aurpkgs[@]}
            fi
        # clean (-Sc) handling
        elif [[ $cleancache ]]; then
            [[ ! $aur ]] && sudo $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
            [[ ! $repo ]] && [[ $fallback = true || $aur ]] && CleanCache ${pkgs[@]}
        # sysupgrade (-Su, -u) handling
        elif [[ $upgrade ]]; then
            [[ ! $selective ]] && ClassifyPkgs ${pkgs[@]} && unset pkgs # selective upgrade switch
            [[ ! $aur ]] && sudo $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
            [[ ! $repo ]] && [[ $aur ]] && [[ $refresh ]] && [[ -z "${repopkgs[@]}" ]] && sudo $pacmanbin -Sy ${pacopts[@]} ${ignoreopts[@]}
            [[ -n "${aurpkgs[@]}" ]] && [[ $fallback = true && ! $aur ]] && note "w" $"Package(s) ${colorW}${aurpkgs[*]}${reset} not found in repositories, trying ${colorM}AUR${reset}..."
            [[ ! $repo ]] && [[ $fallback = true || $aur ]] && Core ${aurpkgs[@]}
        # sync (-S, -y), downloadonly (-Sw, -m), refresh (-Sy)
        else
            [[ -z "${pkgs[@]}" ]] && sudo $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} || ClassifyPkgs ${pkgs[@]}
            [[ -n "${repopkgs[@]}" ]] && sudo $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${repopkgs[@]}
            if [[ -n "${aurpkgs[@]}" ]]; then
                [[ $refresh ]] && [[ -z "${repopkgs[@]}" ]] && sudo $pacmanbin -Sy ${pacopts[@]} ${ignoreopts[@]}
                [[ $fallback = true && ! $aur ]] && note "w" $"Package(s) ${colorW}${aurpkgs[*]}${reset} not found in repositories, trying ${colorM}AUR${reset}..."
                Core ${aurpkgs[@]}
            fi
        fi
        exit;;
    upgrades)
        # upgrades (-Qu, -k) handling
        [[ ! $aur ]] && CheckRepo ${pkgs[@]}
        [[ ! $repo ]] && [[ $fallback = true || $aur ]] && CheckAur ${pkgs[@]}
        exit;;
    *)  # others operations handling
        if [[ -z "${pkgs[@]}" || -n "$(grep -e "-[QTglp]" <<< ${pacmanarg[@]})" ]]; then
            $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${pkgs[@]}
        else
            sudo $pacmanbin ${pacmanarg[@]} ${pacopts[@]} ${ignoreopts[@]} ${pkgs[@]}
        fi
        exit;;
esac
# vim:set ts=4 sw=2 et:
