#!/usr/bin/env perl
#
# Execute a get_image job for the postage stamp server
#

use strict;
use warnings;

use Getopt::Long qw( GetOptions );
use Pod::Usage qw( pod2usage );
use DBI;
use PS::IPP::Metadata::Config;
use PS::IPP::Metadata::Stats;
use PS::IPP::Metadata::List qw( parse_md_list );
use File::Copy;
use File::Basename;
use Digest::MD5::File qw( file_md5_hex );

use PS::IPP::Config qw($PS_EXIT_SUCCESS
		       $PS_EXIT_UNKNOWN_ERROR
		       $PS_EXIT_SYS_ERROR
		       $PS_EXIT_CONFIG_ERROR
		       $PS_EXIT_PROG_ERROR
		       $PS_EXIT_DATA_ERROR
		       $PS_EXIT_TIMEOUT_ERROR
		       metadataLookupStr
		       metadataLookupBool
		       caturi
		       );
my $product;
my $fileset;

my $uri;
my $out_dir;

my $verbose = 1;
my $ipprc;
my $dbname;
my $job_id;
my $rownum;

#
# parse args
#

GetOptions(
        'job_id=s'        =>      \$job_id,
        'rownum=s'        =>      \$rownum,
        'uri=s'           =>      \$uri,
        'out_dir=s'       =>      \$out_dir,
        'dbname=s'        =>      \$dbname,
) or pod2usage(2);

my $err = "";
$err .= "--job_id is required\n" if (!$job_id);
$err .= "--rownum is required\n" if (!$rownum);
$err .= "--uri is required to specify the file list\n" if (!$uri);
$err .= "--out_dir is required to specify the output fileset\n" if (!$out_dir);

die $err if $err;

# collapse any multiple slashes in output_dir
$out_dir = File::Spec->canonpath($out_dir);

my @path = split(/\//, $out_dir);

my $nelem = @path;
if ($nelem < 2) {
    die("$out_dir is not a valid output fileset directory");
}
$fileset = $path[$nelem-1];
$product = $path[$nelem-2];

$_ = $out_dir;
my ($ds_dir) = m%(.*)/$product/$fileset%;

if ($verbose) {
    print STDERR "DS root:  $ds_dir\n";
    print STDERR "Product:  $product\n";
    print STDERR "Fileset:  $fileset\n";
    print STDERR "Filelist: $uri\n";
}


if (!stat("$ds_dir/index.txt")) {
    $err .= "Data Store not found at '$ds_dir'.\n"
}

show_usage("Invalid product '$product'.")
    unless defined stat("$ds_dir/$product/index.txt");

if (! open(INPUT, "<$uri") ) {
    die("failed to open file list: $uri");
}

my $reglist = "$out_dir/reglist";
if (! open(REGLIST, ">$reglist$job_id") ) {
    die("failed to open registration list: $reglist");
}

my @files;
my $num = 0;
while (<INPUT>) {
    chomp;
    my @fields = split /\|/;
    my $pathname = shift @fields;
    my $filetype = shift @fields;
    my $class_id = shift @fields;

    ($pathname , my $filename) = resolvepath($pathname);

    if ($verbose) {
        print STDERR "$pathname @fields\n";
    }

    $num++;
    $filename = "${rownum}_${num}_$filename";
    my $dest_path = "$out_dir/$filename";
    if (! copy $pathname, "$dest_path" ) {
        die("failed trying to copy $pathname to $out_dir");
    }

    # XXX is pstamp always the right file type, if not where can we get the right one?
    print REGLIST file_registration_line($filename, $dest_path, $filetype, $class_id);

    foreach my $f (@fields) {
        print REGLIST "$f|";
    }
    print REGLIST "\n";
}

close(REGLIST);

exit 0;

sub resolvepath {
    my $pathname = $_[0];

    # use the basename of the unresolved file as the name of the file
    # in order to avoid nebulous name mangled paths in the datastore
    my $file = basename($pathname);

    my $slash = index($pathname, "/");
    if ($slash != 0) {
        if (!$ipprc) {
            $ipprc = PS::IPP::Config->new();
        }
        $pathname = $ipprc->file_resolve($pathname);
    }


    return ($pathname, $file);
}

# XXX move this to a module so the code can be shared 
sub file_registration_line {
    my $filename = shift;
    my $path     = shift;
    my $filetype = shift;
    my $chipname = shift;
    $chipname = $chipname ? "$chipname|" : "";

    if (-e $path) {
        my @finfo = stat($path);
        die "failed to stat $path" unless (@finfo);    # XXX clean up
        my $bytes = $finfo[7];
        my $md5sum = file_md5_hex($path);

        return "$filename|$bytes|$md5sum|$filetype|$chipname";
    } else {
        die "$filename not found at $path";
    }
}
