#!/usr/bin/perl
###########################################
# Mike Schilli, 2003 (m@perlmeister.com)
###########################################
use warnings;
use strict;

my $IMG_FILE_DIR = "/ms2/PHOTOS";

use CameraStore;
use Log::Log4perl qw(:easy);
use Image::Info qw(image_info);
use File::Path;
use File::Copy;
use Getopt::Long;
use Pod::Usage;

my $ID_REGEX  = qr#^(\d{4})-(\d\d)-(\d\d)
                  _(\d\d):(\d\d):(\d\d)$#x;
my $TS_REGEX  = qr#^(\d{4}):(\d\d):(\d\d)\s
                   (\d\d):(\d\d):(\d\d)$#x;
my $PIC_REGEX = qr#(\.jpg)$#i;

Log::Log4perl->easy_init(
    { file   => 'stderr',
      level  => $WARN,
      layout => "%p %m%n"});

GetOptions(
  "import"   => \my $import,
  "tag=s"    => \my $tag,
  "untag=s"  => \my $untag,
  "filter"   => \my $filter,
  "list"     => \my $list,
  "grep=s"   => \my $grep,
  "search=s" => \my $search,
  "paths"    => \my $paths) or
pod2usage();

my $db = CameraStore->new();

if($search) {
    for($db->search_tag($search, $paths)) {
        print "$_\n";
    }
    exit 0;
}

my $in = get_input_sub();

while($_ = $in->()) {

    if($import) {
        add_file($db, $_, $tag);
        next;
    }

    my($id) = (-f) ? file_info($_) : $_;
    unless(defined $id and 
           $id =~ /$ID_REGEX/) {
        ERROR "Image $_ not in DB"; 
        next;
    }

    if($tag) {
        $db->add_tag($tag, $id);
    } elsif($untag) {
        $db->delete_tag($untag, $id);
    } elsif($grep) {
        print "$_\n" for
            $db->search_tag($grep, 
                            $paths, $id);
    } elsif($list) {
        print "$_: ", join(', ',
            $db->list_tags($id)), "\n";
    } else {
        pod2usage("Options error");
    }
}

###########################################
sub add_file {
###########################################
    my($db, $ofile, $tag) = @_;

    my($stamp, $dir, $file) = 
                      file_info($ofile);

    return undef unless defined $file;

    if(!-d $dir) {
        mkpath($dir) or 
               LOGDIE "Cannot mkpath $dir";
    }

    copy($ofile, "$dir/$file") or 
       LOGDIE "$ofile > $dir/$file failed";

    $db->add_image($stamp, 
                   "$dir/$file", $tag);
    print "$stamp\n";
}

###########################################
sub file_info {
###########################################
    my($ofile) = @_;

    my ($suffix) = ($ofile =~ $PIC_REGEX);

    unless($suffix) {
        ERROR "Unknown image type: $ofile";
        return undef;
    }

    my($y, $m, $d, $h, $mi, $s) = 
                       image_date($ofile);
    return undef unless defined $s;

    my $stamp = "$y-$m-${d}_$h:$mi:$s";
    my $dir   = "$IMG_FILE_DIR/$y/$m/$d";
    my $file  = "$h:$mi:$s$suffix";

    return($stamp, $dir, $file);
}

###########################################
sub image_date {
###########################################
    my($file) = @_;

    my $info = image_info($file);
    
    if ($info->{error} or
        ! exists $info->{DateTime} or
        $info->{DateTime} !~ $TS_REGEX) {
        WARN "No timestamp from $file";
        return undef;
    }
    return($1, $2, $3, $4, $5, $6);
}

###########################################
sub get_input_sub {
###########################################
    my @items = ();

    if(@ARGV) {
        push @items, @ARGV;
    } else {
        while(<STDIN>) {
            chomp;
            push @items, $_;
        }
    }

    return sub {
        if(@items and -d $items[0]) {
            my $dir = shift @items;
            unshift @items, 
               grep /$PIC_REGEX/, <$dir/*>;
        }
        return shift @items;
    };
}

__END__

=head1 NAME

idb - Image database client

=head1 SYNOPSIS

        # Import and tag
    idb -i -t tag [file|dir] ...
        # Filter files and tag
    ls *.jpg | idb -t tag
        # DB search for tags, print paths
    idb -s search_pattern -p
        # Grep for tags in files
    idb -g search_pattern [file|dir] ...
        # List files/tags
    idb -l [file|dir] ...
