#!/usr/bin/env bash

loc_storage="${HOME}/.config/url-diff";
if [[ ! -z "${URLDIFF_STORAGE_DIR}" ]]; then loc_storage="${URLDIFF_STORAGE_DIR}"; fi

loc_firefox_profile="${loc_storage}/firefox-profile";
loc_prev_images="${loc_storage}/previous-images";

highlight_colour="${URLDIFF_HIGHLIGHT_COLOUR:-#ff000044}";

quiet="${URLDIFF_QUIET:-false}";

window_width="${URLDIFF_WINDOW_WIDTH}";

change_threshold="${URLDIFF_CHANGE_THRESHOLD:-2}";

###############################################################################

if [[ -z "$(type -p calc)" ]]; then
	echo "calc command not detected - it would appear it is not installed" >&2;
	echo "Install it like this on debian systems:" >&2;
	echo "	sudo apt install apcalc" >&2;
fi

###############################################################################

log_msg() {
	if [[ "${quiet}" == "true" ]]; then
		return 0;
	fi
	echo "[${SECONDS}] $*";
}

# $1	Image to process
# $2	Colour to find
calculate_percentage_colour() {
	loc_image="${1}";
	colour="${2}";
	
	if [[ -z "${colour}" ]]; then
		log_msg "calculate_percentage_colour/Error: No colour specified." >&2;
		return 1;
	fi
	
	image_width="$(identify -format "%[fx:w]" "${loc_image}" )";
	image_height="$(identify -format "%[fx:h]" "${loc_image}")";
	pixel_count_colour="$(convert "${loc_image}" -fill black +opaque "${colour}" -fill white -opaque "${colour}" -format "%[fx:w*h*mean]" info:)";
	
	# echo "image_width: ${image_width}, image_height: ${image_height}, pixel_count_colour: ${pixel_count_colour}" >&2;
	
	calc -p "(${pixel_count_colour} / (${image_width}*${image_height})) * 100" | tr -d '~';
}

###############################################################################

mode="${1}";
shift;

if [[ -z "${mode}" ]]; then
	echo -e "Webpage visual diff checker
    By Starbeamrainbowlabs

Usage:
	webpage-diff {subcommand} [{arguments}]

Subcommands:
	check {url} {output_diff_image} [{output_apng}]
		Checks the given URL for differences, and saves a diff
		image to a specified location. Exits with code 0 if
		differences are found, or code 1 if no differences are
		found.
		Optionally generates an animated PNG that alternates
		between the 2 screenshots.

Environment Variables:
	Variable                    Default variable
	----------------------------------------------------------------------
	URLDIFF_STORAGE_DIR         ~/.config/url-diff
		The directory in which previous images are stored to diff
		against. The firefox profile is also stored in here.
	
	URLDIFF_HIGHLIGHT_COLOUR    #ffffffcc
		The colour to highlight any changes in.
	
	URLDIFF_WINDOW_WIDTH
		The window width to tell firefox to screenshot with.
	
	URLDIFF_CHANGE_THRESHOLD	2
		The percentage of the screenshot that should have
		changed for it to count.
		Allows for ignoring random minor rendering artifacts.
" >&2;
fi

# Create the config directories
mkdir -p "${loc_firefox_profile}";
mkdir -p "${loc_prev_images}";


case "${mode}" in
	check )
		url="${1}";
		url_hash="$(echo "${url}" | sha256sum | cut -d ' ' -f 1)";
		loc_output_diffimage="${2}";
		loc_output_apng="${3}";
		
		tmpdir="$(mktemp -d)";
		on_exit() {
			rm -rf "${tmpdir}";
		}
		trap on_exit EXIT;
		
		loc_img_old="${loc_prev_images}/${url_hash}.png";
		loc_img_new="${tmpdir}/new.png";
		
		if [[ ! -d "$(dirname "${loc_output_diffimage}")" ]]; then
			echo "Error: Output directory for diff image does not exist";
			exit 2;
		fi
		
		log_msg "Taking screenshot";
		log_msg "$(firefox --window-size "${window_width}" --profile "${loc_firefox_profile}" --headless --screenshot "${loc_img_new}" "${url}" 2>&1)";
		
		if [[ ! -f "${loc_img_old}" ]]; then
			log_msg "No image exists yet, storing initial snapshot";
			mv "${loc_img_new}" "${loc_img_old}";
			exit 1;
		fi
		# eog "${loc_img_old}";
		# eog "${loc_img_new}";
		
		# img_hash_old="$(identify -quiet -format "%#" "${loc_img_old}")";
		# img_hash_new="$(identify -quiet -format "%#" "${loc_img_new}")";
		
		# Generate the diff image
		compare "${loc_img_old}" "${loc_img_new}" -compose src -highlight-color "${highlight_colour}" "${tmpdir}/diff.png";
		convert "${tmpdir}/diff.png" -transparent "#ffffffcc" "${tmpdir}/transp.png";
		
		# Work out how much of the image has changed
		percentage_changed="$(calculate_percentage_colour "${tmpdir}/transp.png" "${highlight_colour}")";
		
		if [[ -z "${percentage_changed}" ]]; then
			echo "Something went wrong when calculating the percentage changed - no value was returned";
			exit 1;
		fi
		
		log_msg "Changed: ${percentage_changed}%";
		
		# if [[ "${img_hash_new}" == "${img_hash_old}" ]]; then
		if [[ "$(calc -p "${percentage_changed} > ${change_threshold}")" -eq 0 ]]; then
			log_msg "No changes detected.";
			exit 1;
		fi
		
		log_msg "Changes detected, outputting diff image.";
		convert "${loc_img_new}" "${tmpdir}/transp.png" -compose over -composite "${loc_output_diffimage}";
		
		if which optipng >/dev/null 2>&1; then
			log_msg "Optimising new image";
			optipng "${loc_img_new}";
		fi
		
		
		if [[ ! -z "${loc_output_apng}" ]]; then
			log_msg "Making animated PNG";
			cp "${loc_img_old}" "${tmpdir}/0.png";
			cp "${loc_img_new}" "${tmpdir}/1.png";
			ffmpeg -hide_banner -r 1 -i "${tmpdir}/%d.png" -plays 0 "${loc_output_apng}";
		fi
		
		mv "${loc_img_new}" "${loc_img_old}";
		exit 0;
		
		;;
esac