#!/usr/bin/perl -w

# ALE wrapper script
# 
# Copyright (C) 2007 David Hilvert
#
#     This program is free software; you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation; either version 3 of the License, or
#     (at your option) any later version.
# 
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
# 
#     You should have received a copy of the GNU General Public License
#     along with this program.  If not, see <http://www.gnu.org/licenses/>.

chomp ($ale_exec_dir = `dirname $0`);

%defaults = (
	"ALE_BIN" => "$ale_exec_dir/ale-bin",
	"DCRAW" => "dcraw",
	"EXIF_UTILITY" => "exiftool",
);

%devices = (
	"Canon EOS 5D" => "canon_300d",
	"Canon EOS DIGITAL REBEL" => "canon_300d",
);

for $default (keys %defaults) {
	if (!defined $ENV{$default}) {
		$ENV{$default} = $defaults{$default};
	}
}

#
# Perform metadata extraction and conversion
# 

$started_conversion = 0;
undef $global_device;
for ($i = 0; $i < @ARGV; $i++) {
	$arg = $ARGV[$i];

	$i += 10 if $arg =~ /^-?-3dvp$/;
	$i += 10 if $arg =~ /^-?-3dpp$/;
	$i += 2  if $arg =~ /^-?-3dp$/;
	$i += 2  if $arg =~ /^-?-3dv$/;
	$i += 2  if $arg =~ /^-?-ochain$/;
	$i += 3  if $arg =~ /^-?-wm$/;
	$i += 3  if $arg =~ /^-?-wmx$/;

	next if (!-e $arg); 

	if (defined $ENV{"EXIF_UTILITY"} && `which $ENV{"EXIF_UTILITY"}`) {
		if (`$ENV{"EXIF_UTILITY"} $arg | grep '^EV'` =~ /([0-9\.]+)/) {
			$ev = $1;
			if (`$ENV{"EXIF_UTILITY"} $arg | grep '^ISO'` =~ /([0-9\.]+)/) {
				$ev = $ev - log($1 / 100) / log(2);
			}
			@ARGV = (@ARGV[0..$i - 1], "--ev", "$ev", @ARGV[$i..$#ARGV]);
			$i += 2;
		}
	}

	if (defined $ENV{"DCRAW"} && `which $ENV{"DCRAW"}`) {
		$device_info = `$ENV{"DCRAW"} -i $arg 2> /dev/null`;

		next if ($?);

		if (!$started_conversion) {
			print "Extracting frame data";
			$started_conversion = 1;

			#
			# Make a temporary directory for conversion
			#

			use File::Temp qw/ tempdir /;
			
			$tempdir = tempdir("ale.XXXXXXXXX",
			                   CLEANUP => 1,
					   DIR => File::Spec->tmpdir());
		}

		#
		# Get device information
		#

		undef $device;
		foreach $device_string (keys %devices) {
			if ($device_info =~ /$device_string/) {
				$device = $devices{$device_string};
				last;
			}
		}
		if (!defined $device) {
			$device = "canon_300d";
		}

		#
		# Currently, devices must be global.
		#

		if (defined $global_device && $global_device ne $device) {
			die "Multiple device types not yet supported.\n";
		} else {
			$global_device = $device;
		}

		# @ARGV = (@ARGV[0..$i - 1], "--device", "$device", @ARGV[$i..$#ARGV]);
		@ARGV = ("--device", "$device", @ARGV);

		$i += 2;

		#
		# Convert
		#

		$converted_frame = $arg;
		$converted_frame =~ s/(?:\.[^.]*)?$/.pgm/;
		$converted_frame =~ s/.*\///;
		$converted_frame = $tempdir . "/" . $converted_frame;

		`$ENV{"DCRAW"} -t 0 -d -4 -k 0 -r 1 1 1 1 -c $arg > $converted_frame`;

		$ARGV[$i] = $converted_frame;

		#
		# Try to get black level information
		#

		# XXX: The following approach is not obviously correct.

		if (`$ENV{"DCRAW"} -d -v -c $arg 2>&1 1>/dev/null` =~ /black=(\d+)/) {
			$black_unscaled = $1;
			`$ENV{"DCRAW"} -D -4 -c $arg | pgmhist | tail -1` =~ /(\d+)/;
			$maxval_unscaled = $1;
			`pgmhist $converted_frame | tail -1` =~ /(\d+)/;
			$maxval_scaled = $1;
			
			$black_scaled = $black_unscaled
			              * ($maxval_scaled / $maxval_unscaled)
				      / 65535;
			
			@ARGV = (@ARGV[0..$i - 1], "--black", "$black_scaled", @ARGV[$i..$#ARGV]);
			$i += 2;
		}

		print ".";
	}
}

if ($started_conversion) {
	print "\n";
}

@ARGV = ($0, @ARGV);
system { $ENV{"ALE_BIN"} } @ARGV;
