#!/usr/local/bin/bash

# Copyright (c) 2020 Oliver Mahmoudi
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted providing that the following conditions 
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

### mapdircmp - a comparison utility for mapdir(1)

k_flag=0			# keep savefiles flag
v_flag=0			# verbose flag
x_flag=0			# excludes
x_file=
exit_status=0

check_savefile_existence()
{
	local _savefile _choice

	_savefile=$1

	if [ -e $_savefile ] ; then			# Confirm
		echo -n "The savefile: $_savefile already exists. Do you want to overwrite it Yes/No? "
		read -t 30 _choice				# We got 30 seconds to make a choice

		case $_choice in

		[Yy][Ee][Ss] | [Yy] )
			if [ $v_flag -eq 1 ] ; then
				rm -v $_savefile
			else
				:> $_savefile
			fi
			;;
		[Nn][Oo] | [Nn] )
			echo 'Aborted!'
			exit 1
			;;
		*)
			echo "No input received. Terminating."
			exit 1
			;;
		esac
	fi
}

process_files()
{
	local _savefile _directory _excludes_file

	_savefile=$1
	_directory=$2

	check_savefile_existence ~/$_savefile
	
	if [ $v_flag -eq 1 ] ; then
		if [ $x_flag -eq 1 ] ; then
			_excludes_file=$3
			mapdir -fht -s $_savefile -x $_excludes_file $_directory
		else
			mapdir -fht -s $_savefile $_directory
		fi
	else
		if [ $x_flag -eq 1 ] ; then
			_excludes_file=$3
			mapdir -fht -s $_savefile -x $_excludes_file $_directory > /dev/null 2>&1
			if [ $? -ne 0 ] ; then
				echo "Error while running: mapdir -fht -s $_savefile -x $_excludes_file $_directoy"
				exit -1
			fi
		else
			mapdir -fht -s $_savefile $_directory > /dev/null 2>&1
			if [ $? -ne 0 ] ; then
				echo "Error while running: mapdir -fht -s $_savefile $_directoy"
				exit -1
			fi
		fi
	fi
}

check_files()
{
	local _file1 _file2 _retval

	_file1=~/$1
	_file2=~/$2

	if [ $v_flag -eq 1 ] ; then
		diff $_file1 $_file2
	else
		diff $_file1 $_file2 > /dev/null 2>&1
	fi

	_retval=$?

	if [ $_retval -eq 0 ] && [ $v_flag -eq 1 ] ; then
		echo "files are equal"
	elif [ $_retval -ne 0 ] && [ $v_flag -eq 1 ] ; then
		echo "files differ"
		exit_status=100
	elif [ $_retval -ne 0 ] && [ $v_flag -eq 0 ] ; then
		exit_status=100
	fi
}

usage()
{
	echo "usage: mapdircmp [-hkv] [-x excludes_file] savefile1 dirtree1 savefile2 dirtree2"
	echo "	-h: print usage information and exit"
	echo "	-k: keep savefiles"
	echo "	-v: be more verbose"
	echo "	-x excludes_file: files and folders to be excluded"
}

# Point of entry
while getopts ":hkvx:" opt ; do
        case $opt in
                h)
                        usage
						exit $exit_status
                        ;;
                k)
                        k_flag=1		# keep savefiles flag
                        ;;
                v)
                        v_flag=1		# be more verbose
                        ;;
                x)
                        x_flag=1		# excludes from file flag
						x_file=$OPTARG
                        ;;
                \?)
                        echo "unkown flag: -$OPTARG."
                        usage
                        exit 1
                        ;;
        esac
done

shift $((OPTIND-1))

if [ $# -ne 4 ] ; then
	usage
	exit -1
fi

# 1st run
if [ $x_flag -eq 1 ] ; then
	process_files $1 $2 $x_file
else
	process_files $1 $2
fi

# 2nd run
if [ $x_flag -eq 1 ] ; then
	process_files $3 $4 $x_file
else
	process_files $3 $4
fi

# Check for equality
check_files $1 $3

if [ $k_flag -eq 0 ] ; then
	rm ~/$1 ~/$3
fi

exit $exit_status
