#!/usr/bin/bash

# Ktrash - KDE-3.4+ compatible command line trash which
#          currently only uses the local filesystem
# Author: Steven A (stevenaaus@yahoo.com)
# Freebsd port available at www.sourceforge.net/projects/filerenameutils

# TRASH is the directory which contains the subdirectories "files" and "info"
# Non-local files are also found (for eg) here: TRASH=/mnt/knoppix/.Trash-0
# but they have relative "Path=" entries which KTrash doesn't presently handle.

TRASH=${HOME}/.local/share/Trash
EXCLUDE="\."

function Usage () {
	echo "usage:	$NAME [--] FILE(s): trash files
	$NAME             : list contents of trashcan
	$NAME -l|-s       : list contents of trashcan with properties
	$NAME -r FILE(s)  : recover files to current directory
	$NAME -R FILE(s)  : restore files to original location
	$NAME -e          : empty trashcan"
}

function Error () {
	echo "$NAME: $*"
	exit 1
}

function IsEmpty () {
	[ -z "`find -maxdepth 1 -regex \"$EXCLUDE\" -o -print `" ]
	return $?
}

function showSummary () {
	echo -------------------
	printf "%s   %i %s\n" `du -sh | cut -f 1` `find -regex "$EXCLUDE" -o -print | wc -l` "file(s)"
}

########
# main #
########

NAME=`basename "$0"`

# exit straight away if TRASH isn't a directory

if [ ! -d "$TRASH/files" ] ; then
	echo
	echo "$NAME: \"$TRASH\" no such directory."
	echo "Trash does not know where your trash-can is."
	echo "Type \"man $NAME\" , or edit $0 directly."
	echo
	exit 1
fi

case "$1" in

	"" )
		cd $TRASH/files

		IsEmpty && exit 0

		find -maxdepth 1  -regex "$EXCLUDE" -o -printf "%f\000" | xargs -0 ls -d --color --

		showSummary
		;;

	-l|-s) 

		cd $TRASH/files

		IsEmpty && exit 0

		i=0 ; a_max=0 ; b_max=0
		while read LINE ; do
			[ "$LINE" == "." -o "$LINE" == ".." ] && continue
			INFO="$TRASH/info/${LINE}.trashinfo"
			if DEST=$(grep ^Path= "$INFO" 2>/dev/null) ; then
				DEST="`echo $DEST | cut -b 6-`"
				a[$i]="$LINE"
				b[$i]="$(du -s -- "$LINE" | cut -f 1)"
				c[$i]="$DEST"
                [ "${#LINE}" -gt $a_max -a "${#LINE}" -lt 30 ] && a_max="${#LINE}"
				[ "${#b[$i]}" -gt $b_max ] && b_max="${#b[$i]}"
				((i++))
			else
				echo "no path info found for $LINE"
			fi
		done <<EOF
		`ls -1a 2>/dev/null`
EOF

		# display results
		((a_max++))
		for (( j=0 ; $j < $i ; j++ )) ; do
				printf "%${b_max}s  %-${a_max}s (%s)\n" "${b[$j]}" "${a[$j]}" "${c[$j]}" 
		done | sort -n

		showSummary
		;;

	# -r will not strip the _1, _2 extensions from Trashed files

	-r) shift
		[ "$1" == "" ] && Error "missing arg(s)"

		# test the trash for files matching pattern/name $@
		cd $TRASH/files
		[ -z "`ls -1d -- \"$@\" 2>/dev/null`" ] && Error "no such file(s): $@"

		while read LINE ; do
			LINE=${LINE%/}    # bash trick to remove trailing slashes
			LINEDEST="$OLDPWD/$LINE"
			if [ -e "$LINEDEST" -o -L "$LINEDEST" ] ; then
                                echo "** $LINE already exists **" >&2
                        else
				if mv -- "$LINE" "$LINEDEST" ; then
					rm "$TRASH/info/${LINE}.trashinfo"
					echo Untrashed: "$LINE"
				else
					echo "** $LINE not restored **" >&2
				fi
			fi
		done <<EOF
		`ls -1d -- "$@" 2>/dev/null`
EOF
		;;

	-R) shift
		[ "$1" == "" ] && Error "missing arg(s)"

		cd $TRASH/files
		while read LINE ; do
			LINE=${LINE%/}    # bash trick to remove trailing slashes
			INFO="$TRASH/info/${LINE}.trashinfo"
			if DEST=$(grep ^Path= "$INFO" 2>/dev/null) ; then

				# all percent signs are hex numbers and must
				# convert the from %HH to \xHH which echo -e will display as ascii
				DEST="$(echo -e $(echo $DEST | cut -b 6- | sed -e s'/%/\\x/g'))"
				if [ -e "$DEST" -o -L "$DEST" ] ; then
					echo "** $LINE already exists **" >&2
				else
					if [ ! -d "$(dirname -- "$DEST")" ] ; then
						echo "** failed to restore $LINE, directory $(dirname -- "$DEST") doesn't exist **" >&2
					else
						if mv -v --backup=numbered -- "$LINE" "$DEST" ; then
							rm "$TRASH/info/${LINE}.trashinfo"
						else
							echo "** failed to restore $LINE **" >&2
						fi
					fi
				fi
			else
				Error "no such file"
			fi

		done <<EOF
		`ls -1d -- "$@" 2>/dev/null`
EOF
		;;

	-e) if [ "$2" == "" ] ; then
			cd $TRASH/files
			IsEmpty && exit 0
			find -maxdepth 1  -regex "$EXCLUDE" -o -printf "%f\000" \
			| xargs -0 rm -r --

			cd $TRASH/info
			find -maxdepth 1  -regex "$EXCLUDE" -o -printf "%f\000" \
			| xargs -0 rm -r --
		else
			Error "unexpected arg(s)."
		fi ;;

	--?* | -[^-]* ) Usage ;; # matches "-*" and "--*" but not "--"

	* )	### previously was
		#   mv --backup=numbered --target-directory=$TRASH \
		#   -- "$@" && echo Trashed: "$@"
		# but couldn't backup directories

		[ "$1" == "mv" ] && Error "*** '$NAME mv' found, exitting ***"
		[ "$1" == "--" ] && shift

		# if unique mv FILE -> $TRASH/FILE
		# else mv FILE -> $TRASH/FILE -> $TRASH/FILE_1 ( or 2,3,...)

		for j in "$@" ; do

			i=${j%/}    # bash trick to remove trailing slashes

			# test if the file exists (or is a link)
			if [ -e "$i" -o -L "$i" ] ; then

				# sanity check
				if [[ "$(cd "$(dirname -- "$i")" ; /bin/pwd)/$(basename -- "$i")" == ${TRASH}* ]] ; then
					echo "target $i already in trash"
					continue
				fi

				BASENAME=$(basename -- "$i")
				DEST=$TRASH/files/$BASENAME
				FILENAME="$DEST"

				if [ -e "$FILENAME" -o -L "$FILENAME" ] ; then
					# find a valid filename
					INDEX=1
					while [ -e "${FILENAME}_${INDEX}" -o -L "${FILENAME}_${INDEX}" ] ; do
						INDEX=$(($INDEX + 1))
					done
					FILENAME="${FILENAME}_${INDEX}"
				fi

				if mv -- "$i" "$FILENAME" ; then
					echo "KTrashed: $i"
					temp="${TRASH}/info/`basename -- \"$FILENAME\"`.trashinfo"
					echo "[Trash Info]" >"$temp"

					# For the Path= we should convert special chars to %HH like Konqueror
					# but Konqueror restores our filenames ok anyway!
					# and I don't know the list of chars it reguards as special
					# However we must convert % -> %25
					echo Path=$(cd "$(dirname -- "$i")" ; /bin/pwd)/$(basename -- "$i" | sed -e 's/%/%25/g') >>"$temp"

					echo DeletionDate=`date +%FT%T` >>"$temp"
				else
					# if not enough permissions will arrive here
					# mv will have already reported an error message
					echo -n ""
				fi
			else
				echo "'$i': no such file"
			fi
		done ;;
esac
