#!/bin/bash
###########################################################
# script helping in renaming fotos according to exif date #
# viewing or changing values of exif tags.                #
#                                                         #
# License: GNU GPL v3 // (c) Christopher Roy Bratusek     #
#                         <nano@tuxfamily.org> 2014       #
###########################################################

#enough_args REQUIRED_NUMBER ARGS_PASSED
enough_args () {

	if [[ $((${#}-1)) -lt ${1} ]]; then
		echo "${1} arguements required, only $((${#}-1)) given."
		exit 1
	fi

}

#file_exists FILE
file_exists () {

	if [[ ! -f "${1}" ]]; then
		echo "image does not exist."
		exit 1
	fi

}

#allowed_delimiter DELIMITER
allowed_delimiter () {

	delimiters=( - _ , ~ )
	for delimiter in ${delimiters[@]}; do
		if [[ ${delimiter} == ${1} ]]; then
			return=ok
		fi
	done

	if [[ ! ${return} == ok ]]; then
		echo "invalid delimiter. Allowed: ${delimiters[@]}"
		exit 1
	fi

}

odd_even () {

	a=$1

	if [ $((a%2)) -eq 0 ]; then
		echo even
	else	echo odd
	fi

}

#get_exif_value FILE TAG1 TAG2
get_exif_value () {

	file_exists "${1}"

	for tag in "${@:2}"; do
		if [[ ${tag} == [a-z]* ]]; then
			echo -e "Tag: ${tag}\tValue: " \
			$(exif -i "${1}" | grep ^$(tag_database_alpha ${tag}) | gawk -F \| '{print $2}')
		else	echo -e "Tag: $(tag_database_numeric ${tag})\tValue: "\
			$(exif -i "${1}" | grep ^${tag} | gawk -F \| '{print $2}')
		fi
	done
}

#set_exif_value_multiple FILE TAG1 VALUE1 TAG2 VALUE2
set_exif_value () {

	x=-1
	file_exists "${1}"

	if [[ $(odd_even ${#}) == odd ]]; then
		for exifarg in "${@:2}"; do
			x=$((x+1))
			if [[ $(odd_even ${x}) == even ]]; then
				if [[ ${exifarg} == [a-z]* ]]; then
					tag=$(tag_database_alpha ${exifarg})
				else	tag=${exifarg}
				fi
			else
				exif --ifd=0  --tag=${tag} --set-value="${exifarg}" \
					--output="${1}" "${1}" >/dev/null
			fi
		done
	else
		echo "invalid number of arguments, either one tag or one value is mising"
		exit 1
	fi

}

#tag_database
tag_database () {

	echo -e "
tags known to exifutil:

alpha			numeric
===============================
original-date		0x9003
digitized-date		0x9004
color-space		0xa001
width			0xa002
height			0xa003
orientation		0xa001
manufacturer		0x010f
model			0x0110
"

}

#tag_database_alpha TAGNAME
tag_database_alpha () {

	case $1 in
		original-date)	echo 0x9003 ;;
		digitized-date)	echo 0x9004 ;;
		color-space)	echo 0xa001 ;;
		width)		echo 0xa002 ;;
		height)		echo 0xa003 ;;
		orientation)	echo 0xa001 ;;
		manufacturer)	echo 0x010f ;;
		model)		echo 0x0110 ;;
		*)		echo nontag ;;
	esac

}

#tag_database_numeric TAGID
tag_database_numeric () {

	case $1 in
		0x9003) echo original-date ;;
		0x9004) echo digitized-date ;;
		0xa001) echo color-space ;;
		0xa002) echo width ;;
		0xa003) echo height ;;
		0xa001) echo orientation ;;
		0x010f) echo manufacturer ;;
		0x0110) echo model ;;
		*)	echo nontag ;;
	esac

}

#rename_file_exif FILE DELIMITER TAG1/PREFIX TAG2 ...
rename_file_exif () {

	x=-1
	file_exists "${1}"
	allowed_delimiter "${2}"

	for tag in "${@:3}"; do
		x=$((x+1))
		if [[ ${tag} == [a-z]* ]]; then
			if [[ $(tag_database_alpha ${tag}) == nontag && $x == 0 ]]; then
				desired_filename="${tag}${2}"
			elif [[ $(tag_database_alpha ${tag}) == nontag && $x != 0 ]]; then
				echo "ignoring unknown tag ${tag} at non-prefix position"
			else
				value=$(get_exif_value "${1}" ${tag})
				desired_filename="${desired_filename}${value}${2}"
			fi
		else
			if [[ $(tag_database_numeric ${tag}) == nontag && $x == 0 ]]; then
				desired_filename="${tag}${2}"
			elif [[ $(tag_database_numeric ${tag}) == nontag && $x != 0 ]]; then
				echo "ignoring unknown tag ${tag} at non-prefix position"
			else
				value=$(get_exif_value "${1}" ${tag})
				desired_filename="${desired_filename}${value}${2}"
			fi
		fi
	done

	if [[ ${desired_filename: -1} == ${2} ]]; then
		desired_filename=${desired_filename:0:${#desired_filename}-1}
		#normalize file-names (for vFAT)
		desired_filename=${desired_filename//\ /+}
		desired_filename=${desired_filename//\:/.}
	fi

	file=$(basename "${1}")
	suffix=${file/*.}

	filelen=${#file}
	directory=${1:0:-${filelen}}

	desired_filename="${desired_filename}.${suffix}"

	mv "${1}" "${directory}${desired_filename}"

}

case $1 in

	-s | --set )	enough_args 3 "${@:2}" && set_exif_value "${@:2}" ;;
	-g | --get )	enough_args 2 "${@:2}" && get_exif_value "${@:2}" ;;
	-t | --tags )	tag_database ;;
	-r | --rename )	enough_args 3 "${@:2}" && rename_file_exif "${@:2}" ;;
	*  )    echo "
exifutil (0.20140220) help

	-- script helping in renaming fotos according to exif date,
	        viewing or changing values of exif tags. --

	(c) 2014: Christopher Roy Bratusek <nano@tuxfamily.org>
	License: GNU GPL v3 // Homepage: http://www.nanolx.org/

Usage: exifutil [OPTION] [FILE] {VALUES}

Options		Values					Description
=====================================================================================
-s | --set	file tag1 value1 tag2..valueN		change the value of exif tags
-g | --get	file tag1 tag2 tag3			view the value of exif tags
-t | --tags	---					list supported tags
-r | --rename	file delimiter prefix/tag1 tag2..tagN	rename files according to tags
" ;;

esac
