#!/usr/local/bin/perl

use strict;
use warnings;

use lib '/cell_root/software/HPCC/lib/site_perl';
#For testing, use RW replica
#use lib '/afs/.glue.umd.edu/software/HPCC/1.1/lib/site_perl';

use Glue::HPCC::Cluster;
use Glue::HPCC::Utils::FileUtils qw(
	parse_archive_metainfo_file
	write_archive_metainfo_file
);
use Glue::HPCC::Project::Person;
use Glue::HPCC::Project::PersonProject;
use Glue::HPCC::Project::Log;

use Getopt::Long;
#use File::Basename;
#use Time::ParseDate;
#use Data::Dumper;
use POSIX qw(strftime);

sub usage()
{	print STDERR <<EOF;
$0: Edits the metadata for an archived directory

Usage:

To set/unset the DoNotDelete flag
$0 [ GLOBAL_OPTIONS ] -[no]delete PATH

To add a PoC to the excluded PoCs list
$0 [ GLOBAL_OPTIONS ] -exclpoc POCUNAME -reason REASON PATH

PATH should be a full path to the metadata file associated
with an  archived directory.

Recognized GLOBAL_OPTIONS are:
	--debug: Enter debug mode

To set the DoNoDelete flag, use the -nodelete option.  To
unset it, use the -delete option.

To add a PoC to the excluded list, use -exclpoc option
followed by the username of the PoC.  You will also need
to give a reason (the given reason will be prefixed with
the name of the PoC added, and have the date and user running script
appended).  This will also be logged to the PDB log.


EOF
}


#=====================================================================
#	Main
#=====================================================================
	
my $help;
my $debug;
my $dryrun;
my $verbose;

my $delete;
my $poc;
my $reason;

my $path;


my $res = GetOptions(
	#Global options
	'help!' => \$help,
	'debug!' => \$debug,
	'dryrun!' => \$dryrun,
	'verbose!' => \$verbose,

	#Delete flag
	'delete|delete-flag|delete_flag!' => \$delete,

	#Excluded PoClist
	'exclude-poc|exclude_poc|exclpoc|excl-poc|excl_poc|excl|poc=s' => \$poc,
	'reason=s' => \$reason,

);

unless ( $res )
{	usage;
	die "Error parsing options.\n";
}

$path = shift @ARGV;

if ( @ARGV )
{	my $temp = join ", ", @ARGV;
	usage;
	die "Extraneous arguments [ $temp ], aborting.\n";
}

unless ( $path )
{	usage;
	die "You must provide a path to the metadata of an archived directory to modify.\n";
}
unless ( -f $path )
{	die "Unable to find metadata file '$path'.\n";
}


#Default cluster if needed
my $hpc = Glue::HPCC::Cluster->new_from_clustername();
die "\nError instantiating cluster $hpc " unless $hpc && ref($hpc);
my $cluster = $hpc->db_clustername;

$hpc->verbose($verbose);
$hpc->dryrun($dryrun);
#Glue::HPCC::Utils::MailUtils::verbose($verbose);
#Glue::HPCC::Utils::MailUtils::dryrun($dryrun);
Glue::HPCC::Utils::FileUtils::verbose($verbose);
Glue::HPCC::Utils::FileUtils::dryrun($dryrun);

my $metadata = parse_archive_metainfo_file($path);
unless ( $metadata && ref($metadata) eq 'HASH' )
{	die "Error parsing metadata from file '$path': $metadata\n";
}
print STDERR "[DEBUG] Read metadata from $path.\n" if $debug;

my $didsomething = 0;
my $tried2dosomething = 0;
my $old;

my $user = $ENV{USER};
my $today = strftime("%Y-%b-%d", localtime);

if ( defined $delete )
{	$old = $metadata->{DoNotDelete};
	$tried2dosomething++;
	if ( $delete )
	{	#Asked to unset DoNotDelete flag
		if ( $old )
		{	$metadata->{DoNotDelete} = 0;
			$didsomething++;
			print STDERR "[DEBUG]: Unsetting DoNotDelete flag.\n"
				if $debug;
		} else
		{	warn "DoNotDelete flag already unset, nothing to do.\n";
		} 
	} else
	{	#Ask to set DoNotDelete flag
		if ( $old )
		{	warn "DoNotDelete flag already set, nothing to do.\n";
		} else
		{	$metadata->{DoNotDelete} = 1;
			$didsomething++;
			print STDERR "[DEBUG]: Setting DoNotDelete flag.\n"
				if $debug;
		}
	}
}

if ( defined $poc )
{	$old = $metadata->{ExcludePoCs} || [];
	$tried2dosomething++;
	my %temp = map { $_ => undef } @$old;
	if ( exists $temp{$poc} )
	{	warn "PoC $poc already on the excluded list, nothing to do.\n";
	} else
	{	my $oldpocs = join ", ", @$old;
		$oldpocs = '' unless $oldpocs;
		push @$old, $poc;
		my $newpocs = join ", ", @$old;
		$newpocs = '' unless $newpocs;
		$metadata->{ExcludePoCs} = $old;
		print STDERR "[DEBUG]: Added $poc to ExcludePoCs list.\n"
			if $debug;
		$old = $metadata->{ReasonExcludePoCs} || [];
		my $tmp = "$poc: $reason (${today}:$user)";
		push @$old, $tmp;
		$metadata->{ReasonExcludePoCs} = $old;
		print STDERR "[DEBUG]: Added '$tmp' to ReasonExcludePoCs list.\n"
			if $debug;
		$didsomething++;

		#Log what was done
		my $path = $metadata->{DirectoryArchived};
		my $owner = $metadata->{DirectoryOwnerUsername};
		my $owner_projs = $metadata->{DirectoryOwnerProjects} || [];
		my $poc_projs = Glue::HPCC::Project::PersonProject->get_projects_user_is_poc_of(
			$hpc, $poc) || [];
		my %temp = map { $_ => undef } @$owner_projs;
		#Projects common to both
		my @projs = grep { exists $temp{$_} } @$poc_projs;
		my $res;
		foreach my $proj (@projs)
		{	$res = Glue::HPCC::Project::Log->add_log_entry($hpc,
				action_code => 'poc-relinquish-data',
				project => $proj,
				cluster => $hpc->clustershort,
				person => $owner,
				reason => $reason,
				tablename => 'filesystem',
				fieldname => $path,
				oldval => $oldpocs,
				newval => $newpocs,
				description => "PoC $poc OKed the deletion of $path",
			);
			if ( $res )
			{	die "Error adding PDB log entry: $res at ";
			}
		}
		#And once again, under PoCs name (no projects)
		$res = Glue::HPCC::Project::Log->add_log_entry($hpc,
			action_code => 'poc-relinquish-data',
			cluster => $hpc->clustershort,
			person => $poc,
			reason => $reason,
			tablename => 'filesystem',
			fieldname => $path,
			oldval => $oldpocs,
			newval => $newpocs,
			description => "PoC $poc OKed the deletion of $path",
		);
		if ( $res )
		{	die "Error adding PDB log entry: $res at ";
		}
		$hpc->db_commit;
				
				
		
	}
}

unless ( $tried2dosomething )
{	usage;
	die "You must give flags to do something (e.g. --delete/--poc flags).\n";
}

my $outfile = $path;
#$outfile = "${outfile}.hold";
if ( $didsomething )
{	my $res = write_archive_metainfo_file( $outfile, $metadata, { force => 1 } );
	if ( $res )
	{	die "Error writing back metainfo file $outfile: $res\n";
	}
	print "[VERBOSE] Successfully wrote file $outfile.\n" if $verbose || $debug;
} else
{	print "[VERBOSE] No changes made.\n" if $verbose or $debug;
}

exit 0;
