#!/bin/ksh
# exif_where
# Author: Perette Barella
# Copyright 2018 Devious Fish.  All Rights Reserved.
# $Id: exif_where 79 2022-04-21 13:30:55Z perette $

# Open file with window manager
# Author: Perette Barella
# Copyright 2018 Devious Fish.  All rights reserved.
# $Id: launch_document 58 2020-09-27 15:55:59Z perette $

# Korn/zsh shell find a utility to implement something
# Author: Perette Barella
# Copyright 2018 Devious Fish.  All rights reserved.
# $Id: find_implementation 58 2020-09-27 15:55:59Z perette $

function find_implementation {
	typeset impl utility
	for impl
	do
		utility="${impl%%[ 	]*}"
		if whence -p "$utility" >/dev/null 2>&1
		then
			print -- "$impl"
			return 0
		fi
	done
	return 1
}


# Parameters: List of documents or URLs to open.
# Returns: 0 on success, non-0 on error.
function launch_document {
	typeset opener document
	if [[ $(uname -s) == "Darwin" ]]
	then
		opener="open %s"
	else
		# Redirects prevent application X spooge all over the terminal
		if ! opener=$(find_implementation \
			"gnome-open %s >/dev/null 2>&1" \
			"xdg-open %s >/dev/null 2>&1" \
			"gvfs-open %s >/dev/null 2>&1")
		then
			print "$arg0: No file opening utility found for this platform."
			return 1
		fi
	fi
	for document
	do
		typeset cmd=$(printf "$opener" \'"$document"\')
		eval "$cmd"
		typeset result=$?
		# If the command fails and involves a redirect, perform it
		# again without the redirect to show the error.
		if (( result != 0 )) && [[ $opener == *">"* ]]
		then
			eval "${cmd%%">"*}"
		fi
		
	done
	return 0
}

# Korn shell/zsh require
# Author: Perette Barella
# Copyright 2018 Devious Fish.  All rights reserved.
# $Id: require 61 2021-08-09 18:49:07Z perette $

function require {
	typeset requirement
	integer result=0
	for requirement
	do
		if ! whence -p "${requirement%:*}" >/dev/null 2>&1
		then
			print -- "$arg0${arg0+: }${requirement#*:} not found; please install." 1>&2
			result=1
		fi
	done
	(( $result != 0 )) && exit $result
	return 0
}

require exiv2

function decimalize_angle {
	set -- $*
	integer degrees
	float result seconds minutes
	degrees=$(( ${1%/*} / ${1#*/} )) || return 1
	minutes=$(( ${2%/*} / ${2#*/} )) || return 1
	seconds=$(( ${3%/*} / ${3#*/} )) || return 1
	let "result = degrees + (minutes / 60) + (seconds / 3600)"
	print $result
	return 0
}

function extract_latitude_longitude {
	typeset file="$1" latitude longitude lat_dir long_dir tag value

	for tag in Exif.GPSInfo.GPSLatitudeRef Exif.GPSInfo.GPSLatitude \
	           Exif.GPSInfo.GPSLongitudeRef Exif.GPSInfo.GPSLongitude
	do
		value=$(exiv2 -K"$tag" -Pv "$file") || return 1
		case "$tag" in
		    Exif.GPSInfo.GPSLatitudeRef)
			[[ $value == *S* ]] && lat_dir="-"
			;;
		    Exif.GPSInfo.GPSLatitude)
			latitude=$(decimalize_angle "$value") || return 1
			;;
		    Exif.GPSInfo.GPSLongitudeRef)
			[[ $value == *W* ]] && long_dir="-"
			;;
		    Exif.GPSInfo.GPSLongitude)
			longitude=$(decimalize_angle "$value") || return 1
			;;
		    *)
			print "Unhandled case; logic error in script." 1>&2
			exit 99
		esac
	done
	print "$lat_dir$latitude,$long_dir$longitude"
	return 0
	

}

arg0=$(basename "$0")
if [ $# -eq 0 ]
then
	print "Usage: $arg0 <file> ...
Opens Google Maps in a web browser, showing the location specified by
EXIF latitude and longitude within JPEG files."
	exit 1
fi

for file in "$@"
do
	if [ ! -f "$file" ] 
	then
		print "$file: Does not exist or is not a file." 1>&2
		continue
	fi

	# Try to extract the exif date information
	if where=$(extract_latitude_longitude "$file")
	then
		print "Location: $where"
		launch_document "http://maps.google.com?q=$where"
	fi
done

