#!/usr/bin/perl -w -I /opt/eprints3/perl_lib

=pod

=head1 NAME

B<process_transfers> - Find Archivematica records which need new transfers creating for their EPrint.

=head1 SYNOPSIS

B<process_transfers> I<repository_id>

=head1 DESCRIPTION

This script looks for any Archivemata records where new_transfer is set to true and then 
creates a new Archivemtaica transfer for the corresponding EPrint using the Archivematica 
export plugin.

It should be run via a cronjob so that new Archivematica transfers are created periodically
as needed (but not in such a way that overwhelms the repository!)

=head1 ARGUMENTS

=over 8

=item B<repository_id> 

The ID of the eprint repository to use.

=back

=head1 OPTIONS

=over 8

=item B<--help>

Print a brief help message and exit.

=item B<--man>

Print the full manual page and then exit.

=item B<--quiet>

Be very quiet. This option will supress all output unless an error occurs.

=item B<--verbose>

Explain in detail what is going on.
May be repeated for greater effect.

=item B<--version>

Output version information and exit.

=back   

=cut

use EPrints;
use strict;
use Getopt::Long;
use Pod::Usage;

my $version = 0;
my $verbose = 0;
my $force = 0;
my $datasetid = 'eprint'; # default to eprint
my $dataobjid = '';
my $quiet = 0;
my $help = 0;
my $man = 0;
my $limit=0;


Getopt::Long::Configure("permute");

GetOptions(
        'help|?' => \$help,
        'man' => \$man,
        'version' => \$version,
        'verbose+' => \$verbose,
        'silent' => \$quiet,
        'quiet' => \$quiet,
        'datasetid=s' => \$datasetid,
        'dataobjid=s' => \$dataobjid,
		'limit=s' => \$limit,
        'force' => \$force,
) || pod2usage( 2 );
EPrints::Utils::cmd_version( "process_transfers" ) if $version;
pod2usage( 1 ) if $help;
pod2usage( -exitstatus => 0, -verbose => 2 ) if $man;
pod2usage( 2 ) if( @ARGV < 1 );

my $noise = 1;
$noise = 0 if( $quiet );
$noise = 1+$verbose if( $verbose );

my $repoid = shift(@ARGV);
my $session = new EPrints::Session( 1 , $repoid , $noise );
if( !defined $session )
{
        print STDERR "Failed to load repository: $repoid\n";
        exit 1;
}

## To Do ##
# 1. (done) Get a list of all Archivematica records which need a new transfer creating
# 2. If the EPrint is locked, or has pending indexer tasks, skip over it for now.
#    We only want EPrints which are not being modified in any way. If the EPrint 
#    is available, take an Edit Lock.
# 3. (done) Export the EPrint using the Archivematica plugin
# 4. Write the result to file where Archivematica can pick it up
# 5. Record a log of the result in the Arcivhematica record

# Find all the Archivematica records which have a is_dirty set to TRUE
my $ds = $session->dataset( "archivematica" );
my $searchexp = new EPrints::Search( session=>$session, dataset=>$ds );
$searchexp->add_field( $ds->get_field( "is_dirty" ), 'TRUE', "EQ" ) unless $force; # can use --force to match all records

if( $datasetid && $dataobjid )
{
	print "Limiting to $datasetid/$dataobjid\n" if $verbose;
	$searchexp->add_field( $ds->get_field( "datasetid" ), $datasetid, "EQ" );
	$searchexp->add_field( $ds->get_field( "dataobjid" ), $dataobjid, "EQ" );
}
my $list = $searchexp->perform_search;

my $plugin = $session->plugin( "Export::Archivematica::EPrint" );

# Export all the is_dirty = TRUE records, setting is_dirty = FALSE as we go.
print "Found " . $list->count() . " records to process.\n" if $verbose;
my $processed = 0;
$list->map( sub {
	my( $session, $dataset, $am ) = @_;
	
	if ($limit != 0) {return if $processed >= $limit;}

	print "Processing Archivematica ID: " . $am->id . "\n" if $verbose;

	my $obj = $am->get_dataobj();
	my %opts;
	$opts{amid} = $am->id;

	my @results = ( $plugin->output_dataobj( $obj, %opts ) );
	my $warnings = '';
	foreach my $r ( @results )
	{
		print "* $r\n" if $verbose;

		# crude error handling, should give us plenty of context to work with though
		if( $r =~ /\[2\] / ) # if entry starts with [2] (rather than [1]) then there is a warning, add those to the log
		{
			my $warning_snippet=$';
			if (length($warning_snippet)>45){
							$warning_snippet = (substr $warning_snippet, 0, 45).'...';
			}
			$warnings .= $warning_snippet.". ";
		}
		
		if( $r =~ /\[0\] / ) # if entry starts with [0] (rather than [1]) then there is a problem
		{
			my $failure = $';
			print "PROBLEM DETECTED WITH " . $am->id . " CANCELLING\n";
			print "> " . $r . "\n";

			# We need to do the error logging here as we cant alter the Archivematica record while at the same time exporting it.
			$am->add_to_record_log( "process_transfer", $failure.'. '.$warnings, "failure" );
			$am->commit();
			exit(1); # cancel everything else
		}
	}
	$processed++;
	$am->set_value( "is_dirty", 'FALSE' );
        $am->add_to_record_log( "process_transfer", $warnings."processed", "success" );
	$am->commit();
});
print "Processed $processed records\n" if $verbose;
$session->terminate();
