#!/usr/bin/perl
# Copyright (C) 2022 santyf.com
#
# Looks for media files within a directory and extracts its capture date from EXIF metadata, then
# renames each file to YYYYMMDD_HHMM.$ext according to the extracted metadata.
#
# Files whose date metadata is valid will be copied in your desired path which will be the root directory
# along with all found and valid files. Those files that have invalid metadata like "0000:00:00 00:00:00"
# will be in "$dir_output_err/".
#
# Following formats are accepted...
#
# For images:
#    .png
#    .jpeg
#    .jpg
#    .webp
#    .heic
# For videos:
#    .mov
#    .mp4
#    .webm
#    .mkv
#
# LICENSE
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation.  No representations are made about the suitability of this
# software for any purpose.  It is provided "as is" without express or
# implied warranty.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE

use strict;
use warnings;
use Path::Tiny;
use File::Find;
use File::Copy;
use Image::ExifTool;
use Term::ANSIColor;

my $NAME = "MediaRename.pl";
my $VERSION = "$NAME v1.0";
my $dir_source = ".";
my $dir_output = "MediaRename Files";
my $dir_output_err = "misc";
my $file = undef;
my $formats = ".png\$|.jpe?g\$|.webp\$|.heic\$|.mov\$|.mp4\$|.webm\$|.mkv\$";


sub copyFiles($$){
    my ($arg1, $arg2) = @_;
    if(! -d $dir_output) {
	mkdir "$dir_output";
    }
    
    if( ! -d $dir_output_err) {
	mkdir "$dir_output/$dir_output_err";
    } 

    copy("$arg1","$arg2") or die "Something went wrong: $!\n";
}

sub renameFiles($$){
    my ($arg1, $arg2) = @_;

    # Delete path
    (my $str_reg = $arg1 ) =~ s/(^.*\/)|(^.*\\)//g;

    # Extension to lowercase
    (my $str_ext = $str_reg ) =~ s/(^.*\.)//g; $str_ext = lc($str_ext);

    # New filename
    my $date = "$arg2";
    $date =~ s/[:]//g;
    $date =~ s/\s/_/g;
    if($str_ext =~ /mov$|mp4$|webm$|mkv$/gi){
	$date =~ s/^/VID_/g;
    } elsif ($str_ext =~ /png$|jpe?g$|webp$|heic$|png$/gi){
	$date =~ s/^/IMG_/g;
    } else {
	$date =~ s/^/MISC_/g;
    }

    return($date, $str_ext, $str_reg);
}

sub extractExif(){
    my @files;
    my $tool = Image::ExifTool->new;
    my $metadata;
    my $info;
    my $files;

    find ( sub {
	return unless -f;
	return unless /$formats/gi;
	push @files, $File::Find::name;
	   }, $dir_source );

    if (! @files >= 1){
	print("No files were found in '$dir_source'\n");
	exit 1;
    } elsif (@files > 0){
	## Search files with 'CreateDate' key ##
	my $i;
	for($i = 0; $i < @files; $i++){
	    $metadata = $tool->ImageInfo("$files[$i]");
	    $info = $tool->GetInfo('CreateDate');

	    foreach(keys %$info){
		if($_ !~ /"CreateDate"/){
		    if("$$info{$_}" =~ "0000:00:00 00:00:00"){
			my ($date, $str_ext, $str_reg) = renameFiles($files[$i], $$info{$_});
			copyFiles($files[$i], "$dir_output/$dir_output_err/$str_reg");
			print colored ("[ERR] '$files[$i]' has invalid metadata. Copied to '$dir_output/$dir_output_err/$str_reg'", "RED"), "\n";
		    } else {
			my ($date, $str_ext) = renameFiles($files[$i], $$info{$_});
			copyFiles($files[$i], "$dir_output/${date}.${str_ext}");
			print colored ("[OK] '$files[$i]' copied to '$dir_output/${date}.${str_ext}'", "GREEN"), "\n";
		    }
		}
	    }
	}
    }
}

sub help(){
    print STDERR "$VERSION" . "
Usage: $0

  General options
    --dir-source        Specify source directory
    --dir-output        Specify output directory

  Other options
    --help              Shows options
    --version           Shows the version
";
}

sub main(){
    if($#ARGV == -1) {
	help();
	exit;
    }
    
    while($#ARGV > 0) {
	$_ = shift @ARGV;
	if (m/^--?dir-source$/s) { $dir_source = shift @ARGV; }
	if (m/^--?dir-output$/s) { $dir_output = shift @ARGV; }
	if (m/^--?help$/s)       { help(); }
	if (m/^--?version$/s)    { print $VERSION; }
    }
    extractExif();
}

main();
