#! /bin/bash

# msygrep
#
# grep the current price list from msy (which is updated from cron regularly)

# (C) Copyright Craig Sanders <cas@taz.net.au> 2020
#
# This software is licensed under the terms of the GNU GPL version 2 or
# later at your option.

MSYDIR="$HOME/dl/MSY"
PARTS="$MSYDIR/msy.txt"

# DEFAULTS
PATTERN=''
EXCLUDE=''
MIN=''
MAX=''
SORT='-n'
DEBUG=0
VERSION=''

usage () {
SCRIPT_NAME=$(basename $0)
cat <<__EOF__
Usage: $SCRIPT_NAME [OPTIONS] [[-e] pattern...]

OPTIONS:
  -d, --description        sort by description
  -p, --price              sort by price
  -b, --brand              group by brand/model (sort by 1st 4 words of desc,
                           then by price)

  -e, --regexp             include pattern (optional like grep, default)
  -v, --exclude            exclude pattern

  -m, --min                exclude items below this price
  -x, --max                exclude items above this price

  -D, --debug              show generated command before exec

  -h, --help               print this help

  -l, --list               list $MSYDIR

  -V, --VERSION            show version (date) of MSY price-list

Searches are alway case insensitive.

Logical AND searches can be performed with multiple '-e' options, or just by
specifying multiple pattern args. OR can be achieved via alternation (|) in
the pattern. e.g. '$SCRIPT_NAME a b c' searchs for 'a AND b AND c', while
'$SCRIPT_NAME "a|b" c' searches for '(a OR b) AND c'.

Multiple exclusions are OR-ed.

Searches are performed with 'grep -P' because perl-compatible regexps are
needed to do the look-aheads required by logical AND.

__EOF__
}

print_version() {
   YMD=$(date -d "@$(stat -c "%Y" "$PARTS")" '+%Y-%m-%d')
   echo Local copy of MSY Price list is dated $YMD
}

# uses the "getopt" program from util-linux, which supports long
# options...unlike the "getopts" built-in to bash.
TEMP=$(getopt -o 'pdbe:v:m:x:DhlV' \
          --long 'price,description,brand,regexp:,exclude:,min:,max:,debug,help,list,VERSION' \
          -n "$0" -- "$@")

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

eval set -- "$TEMP"

while true ; do
    case "$1" in

       -d|--des**)   SORT='-k2' ; shift ;;
       -p|--pri**)   SORT='-n' ; shift ;;
       #-b|--bra**)   SORT='-k2,2 -k1,1n' ; shift ;;
       -b|--bra**)   SORT='-k2,5 -k1,1n' ; shift ;;

       -e|--reg**)   PATTERN="(?=.*$2)$PATTERN" ; shift 2 ;;
       -v|--exc**)   EXCLUDE="$2|$EXCLUDE" ; shift 2 ;;

       -m|--min**)   MIN="$2" ; shift 2 ;;
       -x|--max**)   MAX="$2" ; shift 2 ;;

       -D|--deb**)   DEBUG=1 ; shift ;;

       -h|--help)    usage ; exit 0 ;;
       -l|--list)    echo -n "$MSYDIR: " ; ls -l "$MSYDIR" ; exit 0 ;;
       -V|--VER*)    VERSION=1 ; print_version; shift ;;

       --)           shift ; break ;;

        *)           echo 'Internal error! ' "$1" ; exit 1 ;;
    esac
done

[ -n $VERSION ] && [ -z "$*" ] && exit 0

for p in "$@" ; do
    PATTERN="(?=.*(?:$p))$PATTERN"
done

[ -z "$PATTERN" ] && usage && exit 1

# build up the command line:
PATTERN="'$PATTERN'"

[ -n "$SORT" ] && SORT="| sort $SORT"

# Exclude items with price of exactly 9999 (which often indicates a
# discontinued product)
AWK='! /^9999\t/'

[ -n "$EXCLUDE" ] && AWK+=" && ! /${EXCLUDE%%|}/"
[ -n "$MIN" ] && AWK+=" && \$1 > $MIN"
[ -n "$MAX" ] && AWK+=" && \$1 < $MAX"

AWK="| awk -v IGNORECASE=1 '$AWK'"

[ "$DEBUG" -ne 0 ] && echo grep -P -i "$PATTERN" "$PARTS" "$AWK" "$SORT" >&2
echo grep -P -i "$PATTERN" "$PARTS" $AWK $SORT | sh
