#!/usr/bin/env bash

# imagemunge
# by Jon Jensen <jon@swelter.net>
# created 2004-09-12

set -euo pipefail
trap 'exit 1' INT

if [[ $# -lt 1 ]]; then
	cat <<EOF >&2
Usage: $0 [-r] [-t] [-o] [-90|-180|-270] file1 [file2 ...]

File metadata options (calls jhead or exiftool):
  -r  rename based on EXIF creation timestamp:
      YYYYMMDD-HHMISS.ext
  -rt rename based on filesystem timestamp:
      YYYYMMDD-HHMISS.ext
  -t  set timestamp of file to EXIF creation timestamp
  -tf set timestamp of file to timestamp in filename

Image transform options (calls jpegtran):
  -o optimize (non-lossy)
 -90 rotate 90 degrees
-180 rotate 180 degrees
-270 rotate 270 degrees

Preserves ownership, creation and modification timestamps (with the
exception of the 1 second increment), and all EXIF data. Transforms
are saved to a temporary file first to avoid data loss in case of a
crash or abort.
EOF
	exit 1
fi

transform=
rename_timestamp=
rename=
touch=
touch_filename=
rename_jpeg=
while [[ "${1:0:1}" = "-" ]]
do
	if [[ $1 = "-90" ]]; then
		transform="$transform -rotate 90"
	elif [[ $1 = "-180" ]]; then
		transform="$transform -rotate 180"
	elif [[ $1 = "-270" ]]; then
		transform="$transform -rotate 270"
	elif [[ $1 = "-o" ]]; then
		transform="$transform -optimize"
	elif [[ $1 = "-r" ]]; then
		rename=1
		rename_jpeg="-n%Y%m%d-%H%M%S"
	elif [[ $1 = "-rt" ]]; then
		rename_timestamp=1
	elif [[ $1 = "-t" ]]; then
		touch=1
		rename_jpeg="$rename_jpeg -ft"
	elif [[ $1 = "-tf" ]]; then
		touch_filename=1
	else
		echo "Ignoring unknown option $1" >&2
	fi
	shift
done

tmpfile=.imagemunge.tmp.$$

for i
do
	type="${i##*.}"
	type="${type,,}"   # convert to lower case
	[[ "$type" = jpg ]] && type=jpeg

	[[ -n "$rename_timestamp" ]] && mv -vn "$i" $(echo "$i" | perl -MPOSIX -nE "chomp; say POSIX::strftime('%Y%m%d-%H%M%S', localtime((stat)[9]))").$type

	if [[ -n "$touch_filename" ]]; then
		ts=$(echo "$i" | perl -nE 's/.*(\d{4})-?(\d\d)-?(\d\d)\D+(\d\d)\D?(\d\d)\D?(\d\d)\D?(\d*).*/$1-$2-${3}T$4:$5:$6$7/s && do { length > 19 and substr($_, 19, 0, "."); say }')
		if [[ -n "$ts" ]]; then
			touch -c -d $ts "$i"
		else
			echo "Error extracting timestamp from filename $i" >&2
		fi
	fi

	if [[ "$type" = jpeg ]]; then
		if [[ -n "$transform" ]]; then
			jpegtran -trim -copy all $transform -outfile $tmpfile "$i"
			if [[ $? -eq 0 ]]; then
				if [[ "$EUID" -eq 0 ]]; then
					chown --reference="$i" $tmpfile
				else
					chgrp -f --reference="$i" $tmpfile
				fi
				chmod -f --reference="$i" $tmpfile
				touch -c --reference="$i" $tmpfile
				mv -f $tmpfile "$i"
				echo "Transformed $i"
			else
				rm -f $tmpfile
				echo "Error transforming $i" >&2
			fi
		fi

		[[ -n "$rename_jpeg" ]] && jhead $rename_jpeg "$i"
	elif [[ "$type" = heic ]]; then
		[[ -n "$transform" ]] && echo "Skipping transformation of non-JPEG file $i" >&2

		[[ -n "$touch" ]] && touch -c -d $(exiftool -DateTimeOriginal -p '$DateTimeOriginal' -d '%Y-%m-%dT%H:%M:%S' "$i") "$i"
		[[ -n "$rename" ]] && exiftool -q -v0 '-FileName<${DateTimeOriginal}%c.'$type -d %Y%m%d-%H%M%S "$i"
	elif [[ "$type" = png ]]; then
		[[ -n "$transform" ]] && echo "Skipping transformation of non-JPEG file $i" >&2

		[[ -n "$touch" ]] && touch -c -d $(exiftool -DateCreated -p '$DateCreated' -d '%Y-%m-%dT%H:%M:%S' "$i") "$i"
		[[ -n "$rename" ]] && exiftool -q -v0 '-FileName<${DateCreated}%c.'$type -d %Y%m%d-%H%M%S "$i"
	elif [[ "$type" = mov || "$type" = mp4 ]]; then
		[[ -n "$transform" ]] && echo "Skipping transformation of non-JPEG file $i" >&2

		[[ -n "$touch" ]] && touch -c -d $(exiftool -m -CreationDate -p '$CreationDate' -d '%Y-%m-%dT%H:%M:%S' "$i") "$i"
		[[ -n "$rename" ]] && exiftool -q -v0 -m '-FileName<${CreationDate}%c.'$type -d %Y%m%d-%H%M%S "$i"
	else
		echo "Skipping file with unsupported extension: $i" >&2
	fi

done
