#!/bin/sh

# Copyright (c) 2007-2012 Aleksey Cheusov <vle@gmx.net>
# All rights reserved.
#
# See LICENSE file
######################################################################

. pkg_online_client.env
. pipestatus

set -e

export LC_ALL=C

usage () {
cat <<EOF
usage: pkg_online_client -h
       pkg_online_client -f
       pkg_online_client -s
       pkg_online_client [-n limit] fsq1 [fsq2 ...]
       pkg_online_client -1|-3|-9|-i [-q] pkgid1 [pkgid2...]
where pkgid is <PKGPATH>,<PKGNAME>
and fsq is <field>:<strategy>:<query>
OPTIONS:
   -h         display this screen
   -s         display available search strategies
   -f         display available fields for search in
   -1         display 1-line information about packages
   -3         display short information about packages
   -9|-i      display full information about packages
   -q         quiet mode, do not print "No matches found" to stderr
   -n <limit>    maximum number of results
EOF
}

if test $# -eq 0; then
    usage
    exit 2
fi

limit=1000000000

while getopts hsf139irqn: f; do
    case "$f" in
        s)    strats=1;;
        f)    dbs=1;;
        9|i)  info=1;;
        3)    shortinfo=1;;
        1)    onelineinfo=1;;
        q)    quiet_mode=1;;
	n)    limit=$OPTARG;;
        h)    usage; exit 0;;
	?)    printf "Run pkg_online_client -h for details\n"; exit 2;;
    esac
done

shift `expr $OPTIND - 1`

on_exit (){
    rm -rf $tmp_dir
}

# temp dir and files
tmp_dir=`mktemp -d /tmp/pkg_online.XXXXXX`
. /usr/pkg/libexec/psu/sig_handler.sh

res_fn=$tmp_dir/result.txt
log_fn=$tmp_dir/errors.log
ok_fn=$tmp_dir/ok

#
extract_strat (){
    runawk -F'\t' -e '{printf "%15s    %s\n", $3, $4}'
}

extract_fields (){
    runawk -F'\t' -v type="$PKG_SUMMARY_TYPE" -e '
	$3 ~ ("^pkgsrc-" type "-index") {
	    sub(/^.*-/, "", $3)
	    print $3
	}'
}

extract_pkgpair (){
    runawk -v limit="$limit" -F'\t' -e \
	'$4 ~ /^00-?database/ {next}
	NF == 4 {print $4; ++cnt; if (cnt == limit) exit 0}' "$@"
}

run_query__fsq (){
    field="`echo $1 | cut -d: -f1`"
    strat="`echo $1 | cut -d: -f2`"
    query="`echo $1 | cut -d: -f3`"

    if test _ = _"$field" -a _ = _"$strat" -a _ = _"$query"; then
	printf 'query format: <field:strategy:query>\n'
	exit 2
    fi

    dbname="pkgsrc-${PKG_SUMMARY_TYPE}-index-${field}"

    set +e
    $PKG_ONLINE_DICT -h "$PKG_ONLINE_SERVER" -p "$PKG_ONLINE_PORT" \
	    -m -f -d "$dbname" -s "$strat" -- "$query" 2> "$log_fn"
    ret=$?
    set -e
    case $ret in
	20)
	    ;;
	0|21)
	    echo '' > "$ok_fn";;
	*)
	    cat "$log_fn" 1>&2
	    return $ret;;
    esac
}

run_query_all (){
    for i in "$@"; do
	if printf '%s\n' "$i" | grep '^[^:]*:[^:]*:[^:]*$' > /dev/null; then
	    run_query__fsq "$i" & #|| return $?
	else
	    echo "Incorrect search pattern '$i'" 1>&2
	    return 1
	fi
    done
    wait
}

run_query (){
    # $i: dbname:strategy:query
    runpipe0 run_query_all "$@" '|' extract_pkgpair '|' sort -u

    if test -f "$ok_fn"; then
	exit 0
    else
	if test -z "$quiet_mode"; then
	    cat "$log_fn" 1>&2
	fi
	exit 20
    fi
}

dict2pkg_summary (){
    sed -n 's,^  ,,p' "$@"
}

# -s
if test $strats; then
    runpipe0 $PKG_ONLINE_DICT \
	-h "$PKG_ONLINE_SERVER" -p "$PKG_ONLINE_PORT" -P - \
	-f -S '|' extract_strat

    exit 0
fi

# -f
if test $dbs; then
    runpipe0 $PKG_ONLINE_DICT \
	-h "$PKG_ONLINE_SERVER" -p "$PKG_ONLINE_PORT" -P - \
	-f -D '|' extract_fields

    exit 0
fi

# hack dict client that DEFINEs quickly multiple queries

# server response parser
quick_hack_client (){
    runawk -v quiet_mode="$quiet_mode" -e '
BEGIN {
   in_def = 0
}

BEGIN {
   hostname = "hostname"
   port     = "port"
}

{
   sub(/\r$/, "")
}

$1 == 150 {
   print $2, "definitions found"
   next
}

$1 == 220 || $1 == 250 {
   next
}

in_def && $1 == "." {
   in_def = 0
   next
}

in_def == 1 {
   print "  " $0
   next
}

$1 == 151 {
   in_def = 1
   printf "%s\t%s\taaa\tbbb\n", hostname, port
   next
}

$1 == 221 {
   exit 0
}

$1 == 552 {
   if (!quiet_mode)
      print "No matches found:", $0 > "/dev/stderr"

   exit 20
}

{
   print "unexpected server response: " $0 > "/dev/stderr"
   exit 30
}
'"$@"
}

# query generator
generate_rfc2229_query (){
    # $1 - dbname
    # $@ - queries

    runawk -e '
    BEGIN {
       dbname = ARGV [1]
       for (i=2; i<ARGC; ++i)
          printf "define %s %s\r\n", dbname, ARGV [i]
       printf "quit\r\n"
    }' "$@"
}

# -i|-9|-3|-1
dbname=''
if test $info; then
    dbname=pkgsrc-${PKG_SUMMARY_TYPE}-info
elif test $shortinfo; then
    dbname=pkgsrc-${PKG_SUMMARY_TYPE}-shortinfo
elif test $onelineinfo; then
    dbname=pkgsrc-${PKG_SUMMARY_TYPE}-onelineinfo
fi

if test $dbname; then
    generate_rfc2229_query "$dbname" "$@" |
    runpipe_base \
	${PKG_ONLINE_NETCAT} "$PKG_ONLINE_SERVER" "$PKG_ONLINE_PORT" '|' \
	quick_hack_client '|' \
	dict2pkg_summary

#    for future versions of 'dict' client
#
#    runpipe0 $PKG_ONLINE_DICT \
#	-h "$PKG_ONLINE_SERVER" -p "$PKG_ONLINE_PORT" -P - \
#	-f -d "$dbname" \
#	"$@" '|' \
#	dict2pkg_summary

    exit $pipestatus_2
fi

# search queries
run_query "$@"
