#!/bin/bash

export PAINT_RED='\033[0;31m';
export PAINT_YELLOW='\033[1;33m';
export PAINT_NOCOLOR='\033[0m';

function die
{
	local exit_code="${1}";
	shift;
	
	echo -n "${PAINT_RED}" >&2;
	printf "${1:-""}" ${@:2} >&2;
	echo -n "${PAINT_NOCOLOR}" >&2;
	exit ${exit_code:-1};
}

function warn
{
	echo -n "${PAINT_YELLOW}" >&2;
	printf "${1:-""}" ${@:2} >&2;
	echo -n "${PAINT_NOCOLOR}" >&2;
}

function sha256sum_compare
{
	[[ "$#" == '0' ]] && exit 2; # No arguments
	[[ "$#" == '1' ]] && exit 3; # Insufficient number of arguments
	return [[ "$(sha256sum "${1}" | read hash _ && echo -n "${hash}" || exit 4;)" != "$(sha256sum "${2}" | read hash _ && echo -n "${hash}" || exit 4;)" ]];
}

function hardlink
{
	[[ -f "${2}" ]] && rm -v "${2}" || exit "${?}";
	ln -v "${1}" "${2}" || exit "${?}";
	return 0;
}

function fdupes_hardlink
{
	local file;
	
	# Input expected to be piped.
	while read file; do
		# If file is not empty, put it into the stack.
		[[ -n "${file}" ]] && { set ${@} "${file}"; continue };
		
		case "$#" in
			'0' ) continue; ;;
			'1' ) die '1' '%s: error: unexpected end of stack after %q.\n' "${0}" "${1}"; ;;
			 ?  ) # Two or more items on the stack.
				# Safety check
				[[ ! -f "${1}" ]] && die '2' '%s: error: %q is not a file or does not exist.\n' "${0}" "${1}"
			
				while [[ -n "${2}" ]]; do
					# If dupe from the list does not exist, we will place a hardlink instead, then. But need to warn.
					[[ ! -e "${2}" ]] && warn '%s: warning: %q does not exist. Hard link will still be created, though.\n' "${0}" "${2}";
					# We are unable to replace directory.
					[[ ! -f "${2}" ]] && die '2' '%s: error: %q is not a file.\n' "${0}" "${2}";
					# If we will delete an already hardlinked dupe, we will do unnecessary work.
					if ! [[ "${1}" -ef "${2}" ]]; then
						#sha256sum_compare && die '3' '%s: error: %q and %q hashes does not match.\n' "${0}" "${1}" "${2}"
						printf '%s: sha256sum_compare %q %q\n' "${0}" "${1}" "${2}" >&2;
						#hardlink "${1}" "${2}" && die '4' '%s: error: unable to hardlink %q and %q\n' "${0}" $"{1}" "${2}"
						printf '%s: hardlink %q %q\n' "${0}" "${1}" "${2}" >&2;
					else
						printf '%s: %q and %q already are the same inode, skipping.\n' "${0}" "${1}" "${2}" >&2;
					fi
					
					[[ -n "${3}" ]] && set "${1}" ${@:3} || set "${1}";
				done
			 ;;
		esac
		
		set --;
	done

	printf 'SIMULATION SUCCESSFUL.\n';
	exit 0;
}

