#!/usr/bin/env bash
VERSION=2.4.2
# trash - the command line trashcan
#
# Copyright (C) 2011-17 Klaatu la Terible
#
# This program 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 3 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

# find the system trash without Autotools
#case "$(uname | tr [:upper:] [:lower:] )" in
#    linux|bsd|sun) BASKET=~/.local/share/Trash ;;
#    darwin) BASKET=~/.Trash ;; # TODO check when around a mac
#    *) BASKET=~/.trash ;;
#esac

# this is set by ./configure && make
BASKET=~/.local/share/Trash
test -d $BASKET/info || mkdir -m 700 -p $BASKET/info 2> /dev/null
test -d $BASKET/files || mkdir -m 700 -p $BASKET/files 2> /dev/null

# empty function
empty() {
    CHECK=$(ls "${BASKET}/files/" )

# is trash already empty?
    if [ "X$CHECK" = "X" ]; then
	echo "You have no files in trash."
    fi

    if [ "X$DRYRUN" = "X1" ]; then
	echo "Pretending to remove: $CHECK"
	ACT="echo"
	KILL=""
    else
	KILL="-delete"
	ACT="find"
    fi

# process verbosity and dry-run options
    $ACT $BASKET -mindepth 1 $KILL
    exit
}

# restore function
restore() {
if [ "X$ARG" != "X" ]; then
    for waste in ${ARG[*]}; do
	ORIGIN=$($REALPATH "${waste}")
	if [ ! -z $RESTORE ]; then
	    $ACT $VERBOSE "$BASKET/files/`basename ${ORIGIN}`" $(grep ${waste} $BASKET/info/`basename "${ORIGIN}".trashinfo` 2> /dev/null | cut -d "=" -f2) 2> /dev/null || echo "File not found in trash. Provide filename as it appears in the output of 'trash --list'"
	    /bin/rm -f $BASKET/info/`basename "${ORIGIN}".trashinfo` 2> /dev/null
	fi
    done
else
    echo "File not found in trash."
    echo "Provide filename as it appears in the output of 'trash --list'"
fi
}

list() {
    ls ${BASKET}/files -A
}

namechk() {
    local __resultvar=$1
    if [ -e "$BASKET/files/${COLLIDER}" ]; then
	local exists=1
    else
	local exists=0
    fi

    eval "$__resultvar"="$exists"
}

version() {
    echo "Trashy, version $VERSION GPLv3"
}

# default action
ACT=${ACT:-mv}
REALPATH='readlink -f'

# process verbose and help and dryrun options
while [ True ]; do
if [ "$1" = "--help" -o "$1" = "-h" ]; then
    echo " "
    echo "trash [--verbose|--dry-run|--empty|--list|--restore] foo"
    echo " "
    exit
elif [ "$1" = "--verbose" -o "$1" = "-v" ]; then
    VERBOSE="-v"
    shift 1
elif [ "$1" = "--list" -o "$1" = "-l" ]; then
    list
    shift 1
elif [ "$1" = "--version" -o "$1" = "-w" -o "$1" = "--which" ]; then
    version
    shift 1
elif [ "$1" = "--dryrun" -o "$1" = "-d" -o "$1" = "--dry-run" ]; then
    ACT="echo"
    DRYRUN=1
    shift 1
elif [ "$1" = "--empty" -o "$1" = "-e" -o "$1" = "--pitch" ]; then
    empty
elif [ "$1" = "--restore" -o "$1" = "-r" ]; then
    RESTORE=1
    shift 1
else
    break
fi
done

# TODO
# if source begins with /run or /media or /mnt ;then
# warn the person that trashing it is copying it from
# that external media onto local drive and do they really
# want to do that?
# either that or we have to make .trash on that device.
# not sure if that is appropriate either.

# sanitize input filenames
ARG=( "${@}" ) #create array, retain spaces
set -e

if [ "X$ARG" != "X" ]; then
    if [ "$RESTORE" = "1" ];then
	restore
	exit
    fi

for c in $(seq 0 $((${#ARG[@]} - 1))) ;do
    waste=`echo "${ARG[$c]}"`
    ORIGIN=$($REALPATH "${waste}" 2> /dev/null) 
    COLLIDER=`basename "${waste}"`

    # check for leading dotslash
    LEADER=`echo "${waste}" | grep "^\.\/"` || LEADER=""
    if [ "${LEADER}" != "" ]; then 
	waste=`echo "${waste}" | cut -b3-`
    fi

    HAS_DOT=`echo "${waste}" | grep "\."` || HAS_DOT=""

	if [ "$HAS_DOT" != "" ];then
	    DOT='.'
	    # propose a file extension
	    EXT=`echo "${waste}"|rev|cut -f1-2 -d'.'|rev` # tar.gz

	    TAR=`echo $EXT | grep tar` || TAR=""
	    if [ "$TAR" != "" ]; then #is tar
		FILE=`echo "${waste}"|rev|cut -f3- -d'.'|rev`
	    else
		# this is not a tar
		FILE=`echo "${waste}"|rev|cut -f2- -d'.'|rev`
		EXT=`echo "${waste}"|rev|cut -f1 -d'.'|rev`
	    fi

	else
	    EXT=""
	    DOT=""
	    FILE=`basename "${waste}"`
	fi

	namechk result

	if [ "$result" -ne 0 ]; then
	    n=1
	    # name collision
	    while [ $n -gt 0 ]; do
		COLLIDER="${FILE}"\ ${n}"$DOT""$EXT"
		namechk result
		if [ "$result" -ne 0 ]; then
		    let "n++"
		else
		    n=0
		    break
		fi
	    done

	    # name collision resolved
	    $ACT $VERBOSE "${waste}" "$BASKET/files/${COLLIDER}"
	    INFO=$BASKET/info/`echo "${COLLIDER}".trashinfo`
	    echo "[Trash Info]" > "${INFO}"
	    echo "Path=${ORIGIN}" >> "${INFO}"
	    echo "DeletionDate=$(date +%Y-%m-%dT%T)" >> "${INFO}"
	else
	    # no name collision
	    INFO=$BASKET/info/`basename "${COLLIDER}"`.trashinfo
	    $ACT $VERBOSE "${waste}" "$BASKET/files/`basename "${COLLIDER}"`"
	    echo "[Trash Info]" > "${INFO}"
	    echo "Path=${ORIGIN}" >> "${INFO}"
	    echo "DeletionDate=$(date +%Y-%m-%dT%T)" >> "${INFO}"
	fi	
    done
fi

if [ "X$VERBOSE" == "X-v" ]; then
    echo "$BASKET is currently $(du -h $BASKET | cut -f1 | tail -n -1) in size."
fi
