#!/usr/bin/env bash
pkgname="manjaro-check-repos"

#
# wget db manjaro
# wget db archlinux
# filter maintener manjaro.org
# diff version
# if not in archlinux -> search in AUR

usage()
{
    cat <<USAGE

    ${0##*/} [branch] command [--help]

    branch:
        unstable(default), testing, stable

    command:
        test [user] [--aur] :
            diff versions, manjaro repos/archlinux stable , or aur if not in archlinux
            user: email name (name@manjaro.org) - empty: all mainteners
            --aur: check in aur if not in archlinux
            --html: output in html file
        --deps: check dependencies
        --dbl: check double

        info plg_name(s) :
            show package infos for arch stable and manjaro all branchs

        diff "previous-branch" "next-branch" :
            compare branch (archlinux, unstable, testing, stable)

        rm
            remove local repos

    --list: list mainteners
    -h or --help: this help

USAGE
}

# for developer, not use config in /etc/
unset LOCAL
[ -f "./archlinux.conf" ] && declare  LOCAL=1;

# fist paramater: manjaro branch
unset SETBRANCH
[[ "$1" =~ "stable" || "$1" == "testing" || "$1" == "archlinux" ]] && { branch="$1"; shift; SETBRANCH=1; } || branch="unstable"

declare -A dirs=(
    ['etc']="/etc/${pkgname}"
    ['repos']="/dev/shm/${pkgname}"  #"/var/lib/repos/"
    ['root']="${dirs[repos]}/${branch}"
    ['conf']="${dirs[repos]}/etc/pacman.conf"
    ['dbpath']="${dirs[repos]}/${branch}/lib/pacman"
)

parse_config()
# where store local repos
{
    ((LOCAL)) && dirs['etc']='.';
    config_file="${dirs['etc']}/config.conf"
    [ ! -f "$config_file" ] && return 0
    d=( $(awk -F= '/^RootDir/ {printf($2)}' "$config_file") )
    [ -z "$d" ] && return 0
    dirs['repos']="${d[0]}"
    dirs['root']="${dirs[repos]}/${branch}"
    dirs['conf']="${dirs[root]}/etc/pacman.conf"
    dirs['dbpath']="${dirs[repos]}/${branch}/lib/pacman"
}
parse_config

if [[ "${1^^}" == "RM" && -n "${dirs['repos']}" ]]; then
    echo ":: remove local repos"
    sudo rm -rfv "${dirs['repos']}"
    exit 0
fi

if [[ "$*" =~ "--help" || "-H" == "${1^^}" ]]; then
    usage
    [ -d  "${dirs['repos']}" ] && tree "${dirs['repos']}"
    exit 0
fi

declare -Ar colors=(
    ['stable']=$(tput setaf 2)      #"\033[0m\033[32m"
    ['testing']=$(tput setaf 3)     #"\033[0m\033[93m"
    ['unstable']=$(tput setaf 1)    #"\033[0m\033[31m"
    ['archlinux']=$(tput setaf 4)   #"\033[0m\033[34m"
    ['end']=$(tput sgr0)            #"\033[0m"	# none
)
color="${colors[$branch]}"

msg_manja(){ echo -e "${color}::${colors['end']} $* ${colors['end']}"; }
msg_arch(){ echo -e "${colors['archlinux']}::${colors['end']} $* ${colors['end']}"; }

set_branch()
# create dirs, make pacman.conf and pacman -Sy
{
    silent="$2"
    dirs['root']="${dirs[repos]}/$1"
    dirs['conf']="${dirs[root]}/etc/pacman.conf"
    dirs['dbpath']="${dirs[repos]}/$1/lib/pacman"

    if ((LOCAL)); then
        [ -z "$silent" ] && echo "local for dev, not use /etc/..."
        dirs['etc']="./"
    fi
    sudo mkdir -p "${dirs['dbpath']}" "${dirs['conf']%/*}"
    if [ ! -f "${dirs['conf']}" ]; then     # new install
        if [ "$1" == "archlinux" ]; then
            sudo cp "${dirs['etc']}/archlinux.conf" "${dirs['conf']}"
        else
            sudo cp "${dirs['etc']}/manjaro.conf" "${dirs['conf']}"
            sudo sed -i -e "s|packages/[a-z]*/\$repo|packages/$1/\$repo|g" "${dirs['conf']}"
        fi
        sudo sed -i -e "s|^RootDir.*|RootDir = ${dirs[root]}|" "${dirs['conf']}"
        sudo sed -i -e "s|^DBPath.*|DBPath = ${dirs[dbpath]}|" "${dirs['conf']}"
        sudo pacman -Syy --logfile "${dirs['root']}/pacman.log" --config "${dirs['conf']}"
    else
        [ -z "$silent" ] \
         && sudo pacman -Sy --logfile "${dirs['root']}/pacman.log" --config "${dirs['conf']}" \
         || sudo pacman -Sy --logfile "${dirs['root']}/pacman.log" --config "${dirs['conf']}" &>/dev/null
    fi
}

diff_branchs()
{
    msg_manja "branch Diff ${colors[$1]}$1${colors[end]} / ${colors[$2]}$2${colors[end]}";
    [[ " archlinux unstable testing stable " == *" $1 "* && " archlinux unstable testing stable " == *" $2 "* ]] || {
        echo "Error: bad value - branch not exists (archlinux unstable testing stable)"
        exit 2
    }
    dirs_old="$dirs"
    for b in archlinux unstable testing stable; do
        [[ "$b" == "$1" || "$b" == "$2" ]] || continue
        set_branch "$b" 1
        pacman -Ssq --config "${dirs['conf']}"  |sort >/tmp/$b.lst #2>/dev/null
    done;
    dirs="$dirs_old"
    if [[ -f "/tmp/$1.lst" && -f "/tmp/$2.lst" ]]; then
        comm -3 /tmp/$1.lst /tmp/$2.lst | sed -e "s|^\t|\t\t\t\t\t${colors[$2]}-$(tput sgr0)|g" -e "s|^\S|${colors[$1]}+$(tput sgr0)&|1"
    fi
    for b in archlinux unstable testing stable; do
        [ -f /tmp/$b.lst ] && rm /tmp/$b.lst
    done
}

pkg_info() # (pkgname pkgname ...)
# short pacman -Si in arch,stable,testing and unstable
{
    dirs_old="$dirs"
    if ((SETBRANCH)); then
        msg_manja "${color}${branch}${colors['end']} -> $*"
        pacman -Sii $* --config "${dirs['conf']}" | grep -v '\-\-$' | sed -e "s| : |${color} : $(tput sgr0)|g"
    else
        for b in archlinux unstable testing stable; do
            [ -d "${dirs['root']%/*}/$b" ] || continue
            set_branch "$b" 1
            echo -e "\n${colors[$b]}::${colors['end']} $b :"
            LANG=C pacman -Si $* --config "${dirs['conf']}" 2>/dev/null | awk '/^Name|^Version|^Build/ {print $0}'
        done;
    fi
    dirs="$dirs_old"
}

pause() { msg_manja "pause..."; read -n1; echo ""; }


msg_manja "branch: ${color}$branch"
#msg_manja "local: $LOCAL"
set_branch "archlinux"
[[ "$branch" != "archlinux" ]] && set_branch "$branch"


if [[ "${1^^}" == "INFO" ]]; then
    shift
    (($#<1)) && { echo "Error: no package parameter"; exit 1; }
    pkg_info $*
    exit 0
fi

if [[ "${1^^}" == "SEARCH" ]]; then
    shift
    (($#<1)) && { echo "Error: no package to find"; exit 1; }
    txt="${*}"
    ((${#txt}<3)) && { echo "Error: text to short"; exit 2; }
    if ((SETBRANCH)); then
        echo ""
        msg_manja "${color}${branch}${colors['end']} -> $*"
        pacman -Ss $* --config "${dirs['conf']}" | sed -e "s|^ |$(tput sgr0;tput setaf 8)&|1" -e "s|^\S|$(tput sgr0;tput setaf 7)&|1"
    fi
    exit 0
fi

if [[ "${1^^}" == "DIFF" ]]; then
    shift
    diff_branchs $*
    exit 0
fi

if [[ "$*" =~ "--deps" ]]; then
    msg_manja "Check manjaro dependencies ${color}${branch}"
    pacman -Dkk --config "${dirs['conf']}"
    exit 0
fi

if [[ "$*" =~ "--dbl" ]]; then
    msg_manja "Check double in manjaro ${color}${branch}"
    while read -r pkg; do
        pacman -Ss --config "${dirs['conf']}" | grep $pkg
    done < <( pacman -Ssq --config "${dirs['conf']}"|sort|uniq -D|uniq )
    exit 0
fi

[[ "$*" =~ "--list" || "${1^^}" == "-L" ]] && {
    msg_manja "List manjaro mainteners, branch ${color}${branch}";
    str=$(LANG=C pacman -Si --config "${dirs['conf']}" | awk -F': ' '/^Packager/ {if ($2 ~ "@manjaro") print $2}'|sort|uniq -c);
    str="${str//</<${color}}";
    echo -e "${str//@/${colors[end]}@}\n";
    exit 0;
}

log_html()
{
    ((HTML)) || return 1
    printf "%s\n" "$*" >> $html_file
}

unset TEST
unset AUR HTML
if [[ "${1^^}" == "TEST" ]]; then
    shift
    TEST=1
    user="$1"
    [[ "${user:0:1}" == "-" ]] && user=""
    msg_manja "User(s) filter: ${color}${user}${colors[end]}@manjaro.org"
    [[ "$*" =~ "--aur" ]] && AUR=1
    ((AUR)) && msg_manja "Use AUR"
    [[ "$*" =~ "--html" ]] && HTML=1
    if ((HTML)); then
        html_file="/tmp/${pkgname}.html"
        echo -e "<html>\n<head>\n<style>\nb { color:#c00; }\n</style>\n</head>\n<body>" > $html_file
        if (($?>0)); then
            unset HTML
        else
            log_html "<h3>$branch</h3>"
            [ -n "$user" ] && log_html "<h3>$user@manjaro.org</h3>"
            log_html "<table>"
        fi
    fi
else
    exit 0
fi



CR="\033[0m\033[31m"	# red
CG="\033[0m\033[32m"	# green
CB="\033[0m\033[34m"	# bleu
CJ="\033[0m\033[33m"	# yellow
ca="\033[1m" 	# Bold
ce="\033[0m"	# end

setcolor_version() # (version1 version2)
{
    declare color="$ce"
    if (( $(vercmp "$1" "$2") < 0 )); then
        color="${CR}"
    elif (( $(vercmp "$1" "$2") > 0 )); then
        color="${CG}"
    fi
    echo -en "$color"
}

msg_pkg() # (pkg, version, inarch, inaur, otherversion)
{
    declare pkg="$1"
    declare version="$2"
    declare inarch="$3"
    declare inaur="$4"
    declare otherversion="$5"
    declare color
    if [[ ! "$args" =~ "--verbose" ]]; then
        [[ "${otherversion}" == "$version" || -z "${otherversion}" ]] && return 0
    fi
    color="$(setcolor_version ${version} ${otherversion})"
    printf "\n${ca}%-35s${ce} %-26s\t" $pkg ${version}
    log_html "<tr><td>$pkg</td><td>${version}</td><td>"
    [ "$inarch" == 0 ] && echo -en "(in arch)" && log_html "(in arch)"
    [ "$inaur" == 0 ] && echo -en "in aur" && log_html "in aur"
    if [[ "$version" != "${otherversion}" ]]; then
        echo -en " ${color} ${otherversion}${ce}"
        (( $(vercmp "$version" "$otherversion") < 0 )) && otherversion="<b>${otherversion}</b>"
        log_html "${otherversion}"
    fi
    log_html "</td></tr>"
}

get_aur_version() # (pkg1 pkg2 pkg3 ...)
{
    # return array
    #  238 packages in aur not in archlinux , 4000 requests per day per IP.
    #  URI maximum length limit of 4443 bytes
    #  200 package in multi info/search
    query_value()
    {
        declare txt="${2##*${1}\"\:\"}"
        echo -n ${txt%%\"*}
    }

    declare res query=""
    for arg in "$@"; do
        query="${query}&arg[]=${arg}"
    done
    #echo "https://aur.archlinux.org/rpc/?v=5&type=info${query}"
    
    declare aurresult=$(curl -Ls -m 6 "https://aur.archlinux.org/rpc/?v=5&type=info${query}")
    if [[ -z "$aurresult" || "$aurresult" =~ 'resultcount":0' ]]; then
        echo "Error: not found in AUR" 1>&2
        return 99
        #exit 1
    fi

    declare IFS=$'\n'
    for res in $(sed 's/},{/\n/g' <<< "$aurresult"); do
        v=$(query_value "Version" "$res") 
        n=$(query_value "Name" "$res")
        echo "$n $v"
    done
}

declare -A aurs=()
query_aur()
{
    # create pkg list not in archlinux
    declare -a aurstofind=()
    declare desc info name pkg version
    for desc in ${dirs[manjaro]}/*/desc; do
        info=( $(read_desc "$desc") )
        name="${info[0]}"
        if [ $(find ${dirs[archlinux]} -type d -name "${name}-[0-9]*" | wc -l ) != "0" ]; then
            :
        else
            if [[ "linux" != ${name:0:5} && ! "$name" =~ "manjaro" ]]; then
                if grep -Eq -n1 "^${name}$" "${dirs['repos']}/packages"; then
                #[[ "$args" =~ "--verbose" ]] && echo "$name in AUR"
                    aurstofind+=( $name )
                fi
            fi
        fi
    done
    [[ "$args" =~ "--verbose" ]] && echo "aurstofind[]: ${aurstofind[@]}"
    # create array result one aur request
    while IFS=' ' read -r pkg version; do
        if [[ -n "$pkg" ]]; then
            [[ "$args" =~ "--verbose" ]] && echo -e "aur: ${pkg}: \t ${version}"
            aurs[$pkg]="$version"
        fi
    done < <(get_aur_version "${aurstofind[@]}")
    aurstofind=()
}

find_aur_version() # (pkg_name)
{
    # replace yay by bash function
    declare -a ret=( $(get_aur_version "$1") )
    [[ "${ret[0]}" == "$1" ]] && printf "${ret[1]}"
}

get_pkgs_infos() 
{
    LANG=C pacman -Si --config "${dirs['conf']}" | awk -F': ' -v user="$user" '/^Name/ {na=$2} /^Version/ {ve=$2} /^Packager/ {if ($2 ~ user"@manjaro") printf("%s %s %s\n",na,ve,$2)}'
}


if ((AUR)); then
    cd "${dirs['repos']}"
    sudo wget "https://aur.archlinux.org/packages.gz" &>/dev/null && sudo gunzip -f "packages.gz"
    cd - &>/dev/null
fi

msg_manja "Check packages / Archlinux"
while IFS=' ' read -r pkg version none; do
    versionArch=$(LANG=C pacman -Si $pkg --config "${dirs['repos']}/archlinux/etc/pacman.conf" 2>/dev/null | awk -F': ' '/Version/ {print $2}')
    if [ -n "$versionArch" ]; then
        msg_pkg "$pkg" "$version" 0 1 "$versionArch"
    else
        if [[ -n "$AUR" && "linux" != ${pkg:0:5} && ! "$pkg" =~ "manjaro" ]]; then
            if grep -Eq -n1 "^${pkg}$" "${dirs['repos']}/packages"; then
                #versionAur=$(yay -Ss "${name}" --aur | awk -F' ' '/^aur\/'${pkg}' / {print $2}')
                versionAur=$(find_aur_version "$pkg")
                msg_pkg "$pkg" "$version" 1 0 "$versionAur"
            fi
        fi
        
    fi
done < <( get_pkgs_infos )
echo -e "\n"

if ((HTML)); then
    log_html "</table></body></html>"
    msg_manja "html output in: $html_file"
fi

exit 0
