#!/usr/local/bin/perl
#
#Adds user as a PoC for a project
#

use strict;
use warnings;
use lib '/cell_root/software/HPCC/lib/site_perl';
#use lib '/afs/.glue.umd.edu/software/HPCC/1.1/lib/site_perl';

use Glue::HPCC::Cluster;
use Glue::HPCC::Project::Person;
use Glue::HPCC::Project::Project;
use Glue::HPCC::Project::PersonProject;
use Glue::HPCC::Project::Log;
use Glue::HPCC::Utils::MailUtils qw(send_template_email);

use Getopt::Long;
use Time::ParseDate;
use POSIX qw(strftime);

#Globals
my @always_cc = (	'payerle@umd.edu',
		);

sub usage()
{	print STDERR <<EOF;
$0: Adds user as a PoC for a project

Usage:
$0 -user USERNAME -project PROJECT -reason REASON \
	[ -cluster CLUSTER ] [ -dryrun ] [ -noemail ]

This script adds USERNAME as a Point-of-Contact (PoC) for
the project named PROJECT in HPC CLUSTER.  CLUSTER will
be defaulted based on what host you are running the command
on.

All modifications will be logged and require a REASON.

Normally, email is sent to all PoCs for the project (including
the new one) informing them of the change.  --noemail will prevent
that.

--dryrun causes actions that would have been taken to just
be printed.

EOF
}

	
#------------------------------------------------------
#		Main
#------------------------------------------------------

my ($help, $dryrun, $verbose);
my ($username, $projname, $reason );
my $do_email = 1;
my $cluster;

my $res = GetOptions(
	'help!' => \$help,
	'dryrun!' => \$dryrun,
	'verbose!' => \$verbose,
	'email!' => \$do_email,

	'cluster=s' => \$cluster,
	'user=s' => \$username,
	'project=s' => \$projname,
	'reason=s' => \$reason,
);

unless ( $res )
{	usage;
	die "\nError processing arguments\n";
}

if ( $help )
{	usage;
	exit 0;
}

my $tmp;
if (scalar(@ARGV) )
{	usage;
	$tmp = join ', ', @ARGV;
	die "\nUnrecognized arguments: [ $tmp ], aborting\n";
}

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

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


unless ($username)
{	usage;
	die "\nMissing required parameter 'user'\n";
}

unless ($projname)
{	usage;
	die "\nMissing required parameter 'project'\n";
}
unless ($reason)
{	usage;
	die "\nMissing required parameter 'reason'\n";
}

my $proj = Glue::HPCC::Project::Project->project_by_name($hpc, $projname);
die "Illegal value $projname for project, not found in PDB.\n" 
	unless $proj;
die "Error looking up project $projname in PDB: $proj.\n" 
	unless ref($proj);

my $error;
my $user = Glue::HPCC::Project::Person->person_by_username($hpc, $username);
die "Error looking up $username in PDB: $user.\n" if $user && ! ref($user);
unless ( $user )
{	#Add user to the PDB

        my @fields = (
                hpc => $hpc,
                user => $username,
                reason => $reason,
                FIXME => 1,
        );

	my $projgrp = $proj->unixgroup;
	my $projgid = getgrnam($projgrp) if $projgrp;
        #Set GID to that of first project with usable GID
        push @fields, gid => $projgid if defined $projgid;

	my $hpcUtil = $hpc->get_hpcUtil;
	my $userUtil = $hpcUtil->user;
        $error = $userUtil->add_user_to_hpc_cluster( @fields);

	#Lookup new user
	$user=Glue::HPCC::Project::Person->person_by_username($hpc, $username);
	die "Cannot find newly created user $username in PDB at "
		unless $user;
	die "Error looking up $username in PDB: $user.\n" unless ref($user);
}

my $perproj = Glue::HPCC::Project::PersonProject->get_project_person_by_names(
	$hpc, $projname, $username);
die "Error looking up user ${username}'s status in $projname: $perproj at "
	if $perproj && ! ref($perproj);
unless ( $perproj )
{	#Need to create a blank entry for person/project
	$perproj = Glue::HPCC::Project::PersonProject->pdb_insert($hpc,
		prj_pkey => $proj->prj_pkey,
		ppl_pkey => $user->ppl_pkey,
	);
	die "Error inserting PersonProject record for project $projname"
		 .  " and user $username: $perproj.\n" if $perproj;
	$perproj = Glue::HPCC::Project::PersonProject->get_project_person_by_names(
			$hpc, $projname, $username);
	unless ( $perproj )
	{	die "Error: cannot find newly created PersonProject " .
			"for project $projname, user $username.\n"
			unless $dryrun;
		#Fake out in dryrun mode
		$perproj = Glue::HPCC::Project::PersonProject->new(
			prj_pkey => $proj->prj_pkey,
			ppl_pkey => $user->ppl_pkey,
		);
	}
	Glue::HPCC::Project::Log->add_log_entry($hpc,
		person => $username,
		project => $projname,
		tablename => 'personproject',
		reason => $reason,
		description => "Insert blank person project record",
		action_code => 'insert-person-project',
	);
}

if ( $perproj->is_poc )
{	die "User $username is already a PoC for project $projname\n" .
		"Nothing to do.\n";
}

$error = $perproj->pdb_update_me($hpc, is_poc => 1 );
die "Error adding user $username as PoC for project $projname: "
	. "$error\n" if $error;
Glue::HPCC::Project::Log->add_log_entry($hpc,
	person => $username,
	project => $projname,
	tablename => 'personproject',
	fieldname => 'is_poc',
	oldval => 0,
	newval => 1,
	reason => $reason,
	description => "Adding user $username as poc of $projname",
	action_code => 'modify-person-project',
);

$hpc->db_commit;
print "PoC added, committing db\n";

#Send email
my $template = "${cluster}_add_poc_to_project.tmplate";
my $newname = $user->fullname;

#Get all PoCs (including newly added PoC)
my $poc_emails = Glue::HPCC::Project::PersonProject->get_poc_emails_for_project(
	$hpc, $projname) || [];
push @$poc_emails, @always_cc;

#REmove duplicates
my %temp = map { $_ => undef } @$poc_emails;
$poc_emails = [ keys %temp ];
my $to_str = join ", ", @$poc_emails;

my $macros = 
{	EMAIL => $to_str,
	NEWPOC => $newname,
	PROJECT => $projname,
	CLUSTER => $cluster,
};

send_template_email($template, $macros) if $do_email;

