#!/bin/bash
# aur-query - interface with AurJson
[[ -v AUR_DEBUG ]] && set -o xtrace
argv0=query
AUR_QUERY_PARALLEL=${AUR_QUERY_PARALLEL:-0}
AUR_QUERY_PARALLEL_MAX=${AUR_QUERY_PARALLEL_MAX:-15}
AUR_QUERY_RPC=${AUR_QUERY_RPC:-https://aur.archlinux.org/rpc/?v=5}
AUR_QUERY_RPC_SPLITNO=${AUR_QUERY_RPC_SPLITNO:-150}
PS4='+(${BASH_SOURCE}:${LINENO}):${FUNCNAME[0]:+${FUNCNAME[0]}(): }'

# default arguments
curl_args=(-fgLsS --tcp-fastopen)

uri_info() {
    awk -v rpc="$AUR_QUERY_RPC&type=info" -v splitno="$AUR_QUERY_RPC_SPLITNO" '{
        if (NR == 1)
            printf "%s&arg[]=%s", rpc, $0
        else if (NR % splitno == 0)
            printf "\n%s&arg[]=%s", rpc, $0
        else if (NR > 1)
            printf "&arg[]=%s", $0
    } END {
        if (NR != 0)
            printf "\n"
    }'
}

uri_search() {
    awk -v rpc="$AUR_QUERY_RPC&type=search&by=$1&arg" '{
        printf "%s=%s\n", rpc, $0
    }'
}

trap_exit() {
    if [[ ! -v AUR_DEBUG ]]; then
        rm -rf -- "$tmp"
    else
        printf >&2 'AUR_DEBUG: %s: temporary files at %s\n' "$argv0" "$tmp"
    fi
}

usage() {
    printf 'usage: %s [-t [info|search] ] [-b by]\n' "$argv0" >&2
    exit 1
}

source /usr/share/makepkg/util/parseopts.sh

opt_short='b:t:'
opt_long=('by:' 'type:')
opt_hidden=('dump-options')

if ! parseopts "$opt_short" "${opt_long[@]}" "${opt_hidden[@]}" -- "$@"; then
    usage
fi
set -- "${OPTRET[@]}"

unset arg_by arg_type
while true; do
    case "$1" in
        -b|--by)
            shift; arg_by=$1 ;;
        -t|--type)
            shift; arg_type=$1 ;;
        --dump-options)
            printf -- '--%s\n' "${opt_long[@]}" ${AUR_DEBUG+"${opt_hidden[@]}"}
            printf -- '%s' "${opt_short}" | sed 's/.:\?/-&\n/g'
            exit ;;
        --) shift; break ;;
    esac
    shift
done

# shellcheck disable=SC2174
mkdir -pm 0700 "${TMPDIR:-/tmp}/aurutils-$UID"
tmp=$(mktemp -d --tmpdir "aurutils-$UID/$argv0.XXXXXXXX") || exit
trap 'trap_exit' EXIT

# set filters
case $arg_type in
      info) uri_write() { uri_info; } ;;
    search) uri_write() { uri_search "${arg_by:-name-desc}"; } ;;
         *) usage ;;
esac

# check for interactive terminal
if [[ -t 0 ]]; then
    cat >&2 <<EOF
Warning: Input is read from the terminal. You either know what you
Warning: are doing, or you forgot to pipe data into $argv0.
Warning: Press CTRL-D to exit.
EOF
fi

# generate curl config
if (( AUR_QUERY_PARALLEL )); then
    mkdir "$tmp"/out
    unset i

    jq -R -r '@uri' | uri_write | while IFS= read -r uri; do
        i=$((i+1))

        printf 'url %s\n' "$uri"
        printf 'output %q\n' "$tmp/out/$i"
    done > "$tmp"/config

else
    jq -R -r '@uri' | uri_write | while IFS= read -r uri; do
        printf 'url "%s"\n' "$uri"
    done > "$tmp"/config
fi

# exit cleanly on empty input (#706)
if [[ ! -s $tmp/config ]]; then
    exit
fi

if (( AUR_QUERY_PARALLEL )); then
    # support parallel transfers (curl >7.66.0)
    curl "${curl_args[@]}" -K "$tmp"/config --stderr "$tmp"/error \
         --parallel --parallel-max "$AUR_QUERY_PARALLEL_MAX"

    # XXX: curl --parallel does not exit >0 on failed transfers, thus
    # stderr has to be checked manually
    # shellcheck disable=SC2181
    if (( $? )) || [[ -s $tmp/error ]]; then
        sort "$tmp"/error | uniq -c >&2
        exit 1
    else
        cat "$tmp"/out/*
    fi
else
    # XXX: discard exit codes to match curl --parallel logic
    curl "${curl_args[@]}" -K "$tmp"/config || exit 1
fi

# vim: set et sw=4 sts=4 ft=sh:
