#!/bin/bash

# This file is part of Mkat
#
# Copyright (C) 2004, 2005 Dmitry Maksyoma <ledestin at amur.ru>.
#
# Mkat is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
# USA.

RCFILE=mkatrc 
[ -f /etc/$RCFILE ] && source /etc/$RCFILE
[ -z "$MKAT_LIBPATH" ] && \
  { echo >&2 "MKAT_LIBPATH not set (edit /etc/$RCFILE)"; exit 1; }
. "$MKAT_LIBPATH/helpers.sh" || exit 1

OPTIONS=(\
  -f "overwrite list file" 'FORCE_OVERWRITE=1' \
  -p=PATH "catalog path instead of a CD" 'CATALOG_PATH=${2%%/}' \
  -t=TAG1,TAG2 "write list file with 'tags: TAG1 TAG2' string" 'TAGS=${2//,/ }' \
  -s=REGEX "search the catalog database" '@REGEX' \
  -S=TAG1,TAG2	"search within tags only" '@TAG_REGEX' \
  -T "don't search tags with -s (no tags)" '?FILTER_TAGS' \
  -a "show what tags can be searched with -S" 'SHOW_AVAILABLE_TAGS=1' \
  -m=FILE "make file md5 sum and search for it in the db" '@MD5FILES' \
  --md5dir=DIR "print files with md5 sums not present in the db" '@DIR'
  -y "cycle { mkat; eject; }" 'CYCLE_CATALOG=1' \
  '-c|--config=FILE' "read FILE instead of the default config (~/.$RCFILE)"\
    'CONFIG="$2"; CHILD_PARAMS=$CHILD_PARAMS\ -c\ \"$CONFIG\"' \
  -q "be quiet" 'CHILD_PARAMS=$CHILD_PARAMS\ -q; GREP_PARAMS="-q"' \
  '-d|--debug'  "debug output" 'DEBUG=1; CHILD_PARAMS=$CHILD_PARAMS\ -d' \
  '-h|--help' "print this help screen" 'usage 0')

function usage {
  echo "usage: $0 [option]"
  print_usage
  exit $1
}

#process parameters
process_options "$@"

#source rc file
#-rc specified config must exist
[ "$CONFIG" ] && \
  ([ -f "$CONFIG" ] || { echo >&2 "file not found: $CONFIG"; exit 1; })
CONFIG=${CONFIG:-~/.$RCFILE}
debug "reading rc file: $CONFIG"
[ -f $CONFIG ] && source $CONFIG

#check that essential variables are defined
ESSENTIAL_VARS=(CD LISTDIR)
for v in ${ESSENTIAL_VARS[@]}; do
  eval "[ -z \"\$$v\" ] && 
    { error '"$v" variable must be defined (see mkatrc(5))'; exit 1; }"
done

make_dir "$LISTDIR"

MKAT="$0${CHILD_PARAMS:+ $CHILD_PARAMS}"
GREP_PARAMS="${GREP_PARAMS:+$GREP_PARAMS }-i -E"
GREP="grep${GREP_PARAMS:+ $GREP_PARAMS}"

if [ $SHOW_AVAILABLE_TAGS ]; then
  grep -h ^tags: $LISTDIR/*.list | awk -F: '{ print $2 }'\
    | awk 'BEGIN{ RS="\n| "}; { if ($0 ~ /^./) print $0 }' | sort -u
  exit
fi

#process --md5dir option
if [ "$DIR" ]; then
  IFS=:; FILES=(`find "$DIR" -type f -printf '%p:'`)
  unset IFS; 
  for f in "${FILES[@]}"; do
    cmd="$MKAT -q -m \"$f\""
    debug "$cmd"; eval $cmd
    [ $? -ne 0 ] && echo "$f";
  done;
  exit
fi

#tag search (-S)
if [ "$TAG_REGEX" ]; then
  debug "grep for tags (-S)"
  FILES="$LISTDIR/*.list"
  cmd="$GREP ^tags:.+$TAG_REGEX \$FILES"
  if [ ${#TAG_REGEX[@]} -gt 1 ]; then
    i=1
    while [ $i -lt ${#TAG_REGEX[@]} ]; do
      cmd="$cmd | $GREP ${TAG_REGEX[$i]}"
      let "i += 1"
    done
  fi
  debug $cmd; RES=`eval "$cmd"`
  #exit if -s isn't present, else RES will be further processed by -s
  #handler
  if [ -z "$REGEX" ]; then
    echo "$RES"
    exit $?
  fi
fi

#search the database with grep (-s option)
if [ "$REGEX" ]; then
  IFS=''; 
  if [ "$RES" ]; then
    cmd="echo -e ${RES//$RET/\\\\n} | $GREP $REGEX"
  else
    cmd="$GREP "$REGEX" "$LISTDIR"/*.list"
  fi
  [ $FILTER_TAGS ] && cmd="$cmd | $GREP -v '(^|:)tags:'"
  if [ ${#REGEX[@]} -gt 1 ]; then
    i=1
    while [ $i -lt ${#REGEX[@]} ]; do
      cmd="$cmd | $GREP ${REGEX[$i]}"
      let "i += 1"
    done
  fi
  debug "command: $cmd"; eval "set +f; $cmd"
  exit $?
fi

#search by md5 sum of a file
if [ "$MD5FILES" ]; then
  cmd="md5sum \"\${MD5FILES[@]}\" | awk '{ printf \"%s|\", \$1 }'\
    | sed 's/|$/\n/' | xargs -ivar $MKAT -s \'var\'"
  debug $cmd; eval $cmd
  exit $?
fi

#catalog many CDs: cycle mkat, eject, wait for user input
if [ $CYCLE_CATALOG ]; then
  while : ; do
    $MKAT && sleep $AUTOFS_DELAY && eject
    read -p "Press Enter when ready..."
    [ $? -eq 0 ] || exit
  done
fi

#catalog the CD
if [ -z "$CATALOG_PATH" ]; then
  [ -z `which isoinfo` ] && { error 'binary not found: isoinfo'; exit 1; }
  LABEL=`isoinfo -d -i $DRIVE | sed -ne 's/Volume id: //p'`
  [ -z "$LABEL" ] && { echo "could not obtain CD label"; LABEL="NO_LABEL"; }
else
  LABEL="$CATALOG_PATH"
fi

if [ "$CATALOG_PATH" ]; then
  FNAME=${CATALOG_PATH#/}
  FNAME=${FNAME//\//.}
  CD=$CATALOG_PATH
  TAGS="$TAGS filesystem"; TAGS=${TAGS# }
else
  FNAME=$LABEL
  TAGS="$TAGS cd"; TAGS=${TAGS# }
fi
[ -d "$CD" ] || { error "directory doesn't exist: $CD.\
  Edit 'CD' variable in config."; exit 1; }
DEST="$LISTDIR/$FNAME.list"
{ [ -z $FORCE_OVERWRITE ] \
  && [ -e "$DEST" ] ; } && \
  { echo >&2 "file already exists: '$DEST'"; exit 1; }

{
echo $LABEL
[ "$TAGS" ] && echo "tags: $TAGS"
IFS='
'
for f in `find $CD -mindepth 1`; do
  rel=`echo "$f" | sed -ne "s!${CD%%/}/!!p"`
  if [ -f "$f" ]; then
    echo -e $rel:`du -h "$f" | awk '{print $1}'`:`md5sum "$f" | awk '{ print $1}'`
  else
    echo $rel
  fi
done
} | tee "$DEST"
