#!/bin/bash

# Author : epithetic


function MissingParam {
	echo "Please specify an original and patched directory: build-unip.bat sourcedir destdir."
	echo "(use root directory of program to maximise compatibility with other patches)"
	exit
}

function MissingDir {
	echo "One or both of the specified directories do not exist."
	exit
}

# Check for 64bit OS, expand to other architectures as needed, this will choose bin/ path
arch=`uname -m`
if [ "$arch" == 'x86_64' ]; then
  os="x64"
else
  os="x86"
fi

clear
echo "---------------------------------------"
echo "--- unipatch v0.8 by epithetic --------"
echo "---------------------------------------"
echo -e "\n\n"

if [[ -z "$1" ]] || [[ -z "$2" ]]; then MissingParam; fi

# Version info (tag installers for compatibility support should need arise)
unipver="UNIP0.8"

source="$1"
dest="$2"
work="$(pwd -P)"

if [[ ! -d "$source" ]] || [[ ! -d "$dest" ]]; then MissingDir; fi


# Get name & desc to display when installing

read -p "Enter an ID for your installer (no spaces): " unipname
unipname=${unipname:-noname}
read -p "Enter prerequisite patch IDs in install order (separated by spaces): " unipreq
unipreq=${unipreq:-█}
read -p "Enter a descriptive title for your installer: " uniptitle
uniptitle=${uniptitle:-Untitled}
read -p "Enter a short description for your installer: " unipdesc
unipdesc=${unipdesc:-No_description}

# Housekeeping

if [[ ! -d "$unipname-unip" ]]; then
	mkdir -p "$unipname-unip"
fi
if [[ -f "$unipname-unip/$unipname-unip.remap" ]]; then
	rm "$unipname-unip/$unipname-unip.remap"
fi
if [[ -f "$unipname-unip/$unipname-unip.info" ]]; then
	rm "$unipname-unip/$unipname-unip.info"
fi


warncount=0
errcount=0

echo -e "\nPreparing to create installer $unipname-unip...\n"

date="$(date '+%d/%m/%Y %H:%M:%S')"
echo "----------------------------------------" >> unipatch-log.txt
echo "$date | Preparing to create installer $unipname-unip..." >> unipatch-log.txt
echo "----------------------------------------" >> unipatch-log.txt
echo "" >> unipatch-log.txt


#Main loop, iterate through files in destination directory
#Set IFS so we handle spaces
OIFS="$IFS"
IFS=$'\n'
for file in `find "$dest" -type f`
do
	IFS="$OIFS"
	destfile="$(realpath "$file")"
	filename="$(basename "$destfile")"
	reldestfile="$(realpath --relative-to="$dest" "$destfile")"
	reldestpath="$(dirname "$reldestfile")"
	# Generate source path
	sourcefile="$source/$reldestfile"
	sourcepath="$(dirname "$sourcefile")"
	# Generate patch path
	patchfile="$unipname-unip/$reldestfile.hdiff"
	patchpath="$(dirname "$patchfile")"
	
	# Make sure patch directory exists
	if [[ ! -d "$patchpath" ]]; then
	mkdir -p "$patchpath"
	fi

	# Check if diff file needs to be remapped
	if [[ ! -f "$sourcefile" ]]; then
		echo "Warning: File $destfile does not have a patchable base file in $source. Provide manual target. (skip or empty = skip)"
		while true; do
			read -e -p "Path: " newpath
			newpath=${newpath:-skip}
			if [[ "$newpath" == 'skip' ]]; then
				skipidentical=1
				echo "Skipping."
				echo "WARNING: $destfile did not have a patchable base file. Skipping." >> unipatch-log.txt
				break
			fi
			if [[ -f "$newpath" ]]; then
				# Get relative path for remap file
				relnewpath="$(realpath --relative-to="$source" "$newpath")"
				patchfile="$unipname-unip/$reldestpath/@$filename.hdiff"
				sourcefile="$newpath"
				winpatchfile="$(echo "$patchfile" | sed "s/\/\.\//\//g" | sed "s/\//\\\/g" | sed "s/ /█/g")"
				winremapfile="$(echo "$relnewpath" | sed "s/\/\.\//\//g" | sed "s/\//\\\/g" | sed "s/ /█/g")"
				echo -n "$winpatchfile $winremapfile " >> "$unipname-unip/$unipname-unip.remap"
				echo -e "\r" >> "$unipname-unip/$unipname-unip.remap"
				# log missing to file
				echo "WARNING: $destfile was remapped to $newpath." >> unipatch-log.txt
				warncount=$((warncount + 1))
				skipidentical=0
				break
			else
				echo "$newpath is not a valid file, try again"
				echo ""
			fi
		done
	else
		# Check if files are identical
		skipidentical=0
		sourcefile="$(realpath "$sourcefile")"
		if cmp --silent -- "$sourcefile" "$destfile"; then
			warncount=$((warncount + 1))
			echo "Warning: File $destfile identical to base file. Skipping."
			# log identical to file
			echo "WARNING: $destfile identical to $sourcefile. Skipping." >> unipatch-log.txt
			skipidentical=1
		else
			#  files are different, continue
			:
		fi
	fi
	
	# Generate diff file
	if [[ "$skipidentical" -eq 0 ]]; then
		if [[ -f "$patchfile" ]]; then
			rm "$patchfile"
		fi
		
		bin/$os/hdiffz -m-1 -cache -SD -c-bzip2 "$sourcefile" "$destfile" "$patchfile" >> unipatch.tmp
		# Did hdiffz succeed?
		statusok="$(grep -F "patch check diff data ok" "unipatch.tmp")"
		if [[ -z "$statusok" ]]; then
			echo "ERROR in processing $destfile, check unipatch-log.txt"
			echo "ERROR in processing $destfile." >> unipatch-log.txt
			errcount=$((errcount + 1))
		else
			echo "processed $destfile successfully."
		fi
		cat unipatch.tmp >> unipatch-log.txt
		rm unipatch.tmp
	fi
done

IFS="$OIFS"

# Write version, name & desc to info file
echo -n "$unipver " >> "$unipname-unip/$unipname-unip.info"
echo -e "\r" >> "$unipname-unip/$unipname-unip.info"
echo -n "$uniptitle " >> "$unipname-unip/$unipname-unip.info"
echo -e "\r" >> "$unipname-unip/$unipname-unip.info"
echo -n "$unipdesc " >> "$unipname-unip/$unipname-unip.info"
echo -e "\r" >> "$unipname-unip/$unipname-unip.info"
if [[ "$unipreq" == '█' ]]; then
	echo -e "\r" >> "$unipname-unip/$unipname-unip.info"
else
	echo -n "$unipreq " >> "$unipname-unip/$unipname-unip.info"
	echo -e "\r" >> "$unipname-unip/$unipname-unip.info"
fi

# Remove empty directories left over
find "$unipname-unip" -type d -empty -delete >> unipatch-log.txt


echo -e "\nFinished generating installer $unipname-unip with $warncount warnings and $errcount errors."

exit
