#!/usr/bin/perl -w

use FindBin;
use lib "$FindBin::Bin/../../perl_lib";

######################################################################
#
#
######################################################################

=pod

=head1 NAME

B<issues_audit> - Update the issues field of all eprints.

=head1 SYNOPSIS

B<issues_audit> I<repository_id> [B<options>] [eprint ids]

=head1 DESCRIPTION

This script updates the Issues field of all eprints 
in the live archive and buffer. 

This script should probably be called from your "cron" system, soon after
midnight. Something like:

 # 00:23 every morning
 23 0 * * * /opt/eprints3/bin/isseus_audit my_repo_id

This script will take longer as your repository grows, so initially you may 
want to run it more frequently, or on very large systems you might move to
just run it on Sundays.

=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 vewwy vewwy 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;
use Data::Dumper;

my $version = 0;
my $verbose = 0;
my $quiet = 0;
my $help = 0;
my $man = 0;

Getopt::Long::Configure("permute");

GetOptions( 
	'help|?' => \$help,
	'man' => \$man,
	'version' => \$version,
	'verbose+' => \$verbose,
	'silent' => \$quiet,
	'quiet' => \$quiet
) || pod2usage( 2 );
EPrints::Utils::cmd_version( "send_alerts" ) 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 );

# Set STDOUT to auto flush (without needing a \n)
$|=1;

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;
}

sub _set_item_issues($$);

##############################

#my $file = $session->config( "config_path" )."/issues2.xml";
#if( -e $file )
#{
#	my $doc = $session->get_repository->parse_xml( $file , 1 );
#	if( !defined $doc )
#	{
#        	EPrints::abort "Error parsing $file\n";
#	}
#	
#	my $issues_conf = ($doc->getElementsByTagName( "issues" ))[0];
#	if( !defined $issues_conf )
#	{
#        	EPrints::abort "Missing <issues> tag in $file\n";
#	}
#}
#else
#{
#	print "No $file - skipping\n" if( $noise > 1 );
#}

my $ds = $session->get_archive()->get_dataset( 'eprint' );
my $list;
if( @ARGV )
{
	$list = EPrints::List->new(
		session => $session,
		dataset => $ds,
		ids => \@ARGV,
	);
}
else
{
	$list = $ds->search(
		filters => [
			{ meta_fields => [qw( eprint_status )], value => "inbox buffer archive deletion",
			match => "EQ", merge => "ANY", }
		]);
}

# Run all available Issues plugins
my @issues_plugins = $session->get_plugins(
	type=>"Issues2",
	is_available=>1 );
my %item_issues;
my %info;

foreach my $plugin (@issues_plugins)
{
	$info{$plugin} = {
		issues => \%item_issues,
		opts => {
			list => $list,
		},
	};
}

my $total = $list->count;
my $i = 0;

print "Running plugins: ".join(', ', map { $_->get_name() } @issues_plugins)."\n" if( $noise > 0 );

$list->map(sub {
	my( undef, undef, $item ) = @_;
	foreach my $plugin ( @issues_plugins )
	{
		$plugin->process_item_in_list( $item, $info{$plugin} );
	}
	print sprintf("% 3s%%\r", sprintf("%d", $i++ / $total * 100)) if $noise > 1;
});

foreach my $plugin ( @issues_plugins )
{
	print "Finishing plugin ".$plugin->get_name()."\n" if( $noise > 0 );
	$plugin->process_at_end( $info{$plugin} );
}

$i = 0;

# Update the issues fields
print "Updating database\n" if $noise > 0;
$list->map(sub {
	my( undef, undef, $item ) = @_;

	print sprintf("% 3s%%\r", sprintf("%d", $i++ / $total * 100)) if $noise > 1;

	my $value = $item_issues{$item->id};
	$value = [] if !defined $value;
	for(@$value)
	{
		my $desc = $session->xml->to_string( $_->{description} );
		$session->xml->dispose( $_->{description} );
		$_->{description} = $desc;
	}
	# $item->set_item_issues( $value );
	_set_item_issues( $item, $value );
	$item->commit;
});
print "Done updating database\n" if $noise > 0;


$list->dispose;


#####################################

$session->terminate();
exit;

#####################################

sub _set_item_issues($$)
{
        my( $self, $new_issues ) = @_;

        $new_issues = [] if !defined $new_issues;

        # tidy-up issues (should this be in the calling code?)
        for(@$new_issues)
        {
                # default status to "discovered"
                $_->{status} = "discovered" if !EPrints::Utils::is_set( $_->{status} );

                # default item_issue_id to item_issue_type
                $_->{id} = $_->{type} if !EPrints::Utils::is_set( $_->{id} );

                # default timestamp to 'now'
                $_->{timestamp} = EPrints::Time::get_iso_timestamp;

                # backwards compatibility
                if( ref( $_->{description} ) )
                {
                        $_->{description} = $self->{session}->xhtml->to_xhtml( $_->{description} );
                }
        }

        my %issues_map = map { $_->{id} => $_ } @$new_issues;

        my $current_issues = $self->value( "item_issues2" );
        $current_issues = [] if !defined $current_issues;
        # clone, otherwise we can't detect changes
        $current_issues = EPrints::Utils::clone( $current_issues );

        # update existing issues
        foreach my $issue (@$current_issues)
        {
                my $new_issue = delete $issues_map{$issue->{id}};
                if( defined $new_issue )
                {
                        # update description (may have changed)
                        $issue->{description} = $new_issue->{description} unless ! $new_issue->{description};
                        $issue->{status} = $new_issue->{status} unless $issue->{status} && $issue->{status} eq "ignored";
                }
                elsif( $issue->{status} eq "discovered" )
                {
                        ## $issue->{status} = "autoresolved";
                }
        }

        # append all other new issues
        foreach my $new_issue (@$new_issues)
        {
                next if !exists $issues_map{$new_issue->{id}};
                push @$current_issues, $new_issue;
        }

        $self->set_value( "item_issues2", $current_issues ); # key difference
}




=head1 COPYRIGHT

=for COPYRIGHT BEGIN

Copyright 2000-2011 University of Southampton.

=for COPYRIGHT END

=for LICENSE BEGIN

This file is part of EPrints L<http://www.eprints.org/>.

EPrints is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

EPrints is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License
along with EPrints.  If not, see L<http://www.gnu.org/licenses/>.

=for LICENSE END

