set -e

if [ -z "$BUILDBOX" ]; then
	echo "Missing buildbox path" >&2
	exit 1
fi

if ! [ -x "$(command -v sha256sum)" ]; then
	echo "sha256 is required to run tests" >&2
	exit 1
fi
if ! [ -x "$(command -v fusermount3)" ]; then
	echo "fusermount3 is required to run tests" >&2
	exit 1
fi

TMPDIR=$(mktemp -d)
ROOT="$TMPDIR/mnt"
mkdir "$ROOT"
mkdir "$TMPDIR/cas"

TIMES="times.out"

cleanup() {
	stop_buildbox
	rm -rf "$TMPDIR"
}
trap cleanup INT TERM EXIT

start_buildbox() {
	if [ -s "$TMPDIR/in" ]; then
		IN_ARGS="--input-digest=$TMPDIR/in"
	else
		IN_ARGS=""
	fi
	local TIMEOUT=10
	local START=$SECONDS
	"$BUILDBOX" --output-times="$TMPDIR/$TIMES" --local="$TMPDIR/cas" $IN_ARGS --output-digest="$TMPDIR/out" $REMOTE_ARGS "$ROOT" &
	BUILDBOX_PID=$!
	# Wait until mount is complete
	while ! mountpoint -q "$ROOT"; do
		if ! kill -0 $BUILDBOX_PID 2>/dev/null; then
			echo "BUILDBOX process has terminated."
			exit 1
		fi
		sleep 0.1
		local ELAPSED=$((SECONDS - START))
		# Check if the timeout has been reached
		if [ $ELAPSED -ge $TIMEOUT ]; then
			echo "Timeout reached: Failed to detect open port for CAS server process $CAS_SERVER_PID within $TIMEOUT seconds."
			exit 1
		fi
	done
}

stop_buildbox() {
	if mountpoint -q "$ROOT"; then
		fusermount3 -u "$ROOT"

		local TIMEOUT=10
		local START=$SECONDS
		# Wait until unmount is complete and output digest has been written
		while mountpoint -q "$ROOT" || [ ! -s "$TMPDIR/out" ]; do
			sleep 0.1
			local ELAPSED=$((SECONDS - START))

			# Check if the timeout has been reached
			if [ $ELAPSED -ge $TIMEOUT ]; then
				echo "Timeout reached: Unmount did not complete or output digest was not written within $TIMEOUT seconds."
				exit 1
			fi
		done
	fi
}

restart_buildbox() {
	stop_buildbox

	# Use previous output tree as new input tree
	mv "$TMPDIR/out" "$TMPDIR/in"

	if [ -n "$REMOTE_ARGS" ]; then
		# Delete local cache if remote is configured
		rm -rf "$TMPDIR/cas"
		mkdir "$TMPDIR/cas"
	fi

	start_buildbox
}

checksum_tree() {
	cd "$1"
	find -print0 | LC_ALL=C sort -z | tar -c --no-recursion --null -T - --mtime=/dev/null --hard-dereference | sha256sum
}

compare_trees() {
	if [ "$(checksum_tree $1)" != "$(checksum_tree $2)" ]; then
		echo "Contents of FUSE mount do not match reference directory" >&2
		echo "$1" - "$2" >&2
		exit 1
	fi
}
