#!/usr/bin/perl -w

use strict;
use Getopt::Std;
use File::Find;
use Image::ExifTool qw(:Public);
use File::stat;
use File::Copy;
use File::Spec;
use File::Basename;

# Globals
use vars qw( %opt %files );

$|++;

getopts('hvs:t:', \%opt) or usage();
usage() if $opt{h};
usage() if scalar keys %opt == 0;

if (! -d $opt{s}) {
	print "The source is not a folder!\n";
	exit;
}
if (! -d $opt{t}) {
	print "The target is not a folder!\n";
	exit;
}

print "Scanning source directory  ";

find(\&scan_files, $opt{s});

print "\nDone!\nCopying  ";


# Hash now contains all files that should be copied
foreach (keys %files) {
	
	print ".";
	
    #print $files{ $_ }."\n";

	my $src = $files{ $_ };

	# Get the target folder and file name
	my $rtgt = $src;
	$rtgt =~ s/^$opt{s}//;				# Remove original slash
	$rtgt =~ s/^\///;					# Remove initial slash
	$rtgt =~ s/\/(raw|jpeg|jpg)\//\//i;	# Remove special folder names (RAW, JPEG, JPG) to flatten the structure

	my $tgt = File::Spec->catfile( $opt{t}, $rtgt );
	my $btgt = dirname($tgt);

	`mkdir -p "$btgt"`;
	copy "$src", "$tgt";

	#print "  ->  $rtgt\n";
	#print "  =>  $tgt\n";
}	
print "\nDone!\n";


sub scan_files {

	if (-d $File::Find::name) {
		return;
	}
	
	print ".";

	if( /(cr2|jpg|jpeg)$/i ) {

		my $info = ImageInfo($File::Find::name);
		
		# Show a warning if the required tags do not exist
		if (! exists $$info{DateTimeOriginal} || ! exists $$info{SerialNumber}) {
			print "\nWARNING: ". $File::Find::name ." is invalid\n";
			return;
		}
		
		my $key = $$info{DateTimeOriginal}."_".$$info{SerialNumber};
		
		if (exists $files{ $key }) {
			# Hash key already exists, check which we should keep
			$files{ $key } = compare($files{ $key }, $File::Find::name);
		} else {
			# New hash key
			$files{ $key } = $File::Find::name;
		}		
	}	
}

sub compare {
	my ($first, $second) = @_;

    # Keep CR2 over JPG
    if( ($first =~ /cr2$/i) && ($second =~ /(jpg|jpeg)$/i) ) {
    	return $first;
    }
    if( ($second =~ /cr2$/i) && ($first =~ /(jpg|jpeg)$/i) ) {
    			return $second;
    }

	# Pick the largest
    my $first_size = -s $first;
    my $second_size = -s $second;
		
	return $first_size > $second_size ? $first : $second;
}


sub usage {	
	print <<EOF;

This program copies a hierarchy of images from one location
to another. Only JPEG/JPG files and Canon RAW (CR2) files
are processed. If two files have the same original time and
serial number only the raw file is copied.

usage: $0 [-hv] [-s folder] [-t folder]
-h        : this (help) message
-v        : verbose output
-s        : source folder
-t        : target folder

EOF

	exit;
}

