#!/bin/env perl

# dquery_finish.pl

use warnings;
use strict;

use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
use Pod::Usage qw( pod2usage );

use Sys::Hostname;
use IPC::Cmd 0.36 qw( can_run run );
use File::Temp qw( tempfile );
use File::Copy;

use PS::IPP::Metadata::Config;
use PS::IPP::Metadata::Stats;
use PS::IPP::Metadata::List qw( parse_md_list );

use PS::IPP::Config qw( :standard );

my ( $req_id, $req_name, $req_file, $product, $outdir, $dbname, $dbserver, $verbose, $save_temps );

GetOptions(
           'req_id=s'   => \$req_id,
           'req_name=s' => \$req_name,
           'req_file=s' => \$req_file,
           'product=s'  => \$product,
           'outdir=s'   => \$outdir,
	   'dbname=s'   => \$dbname,
	   'dbserver=s' => \$dbserver,
	   'verbose'    => \$verbose,
	   'save-temps' => \$save_temps,
) or pod2usage( 2 );

pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;

my $err = "";

$err .= "--req_id is required\n" if !$req_id;
$err .= "--req_name is required\n" if !$req_name;
$err .= "--product is required\n" if !$product;
$err .= "--outdir is required\n" if !$outdir;

die "$err" if $err;

my $missing_tools;

my $pstamptool  = can_run('pstamptool')  or (warn "Can't find pstamptool"  and $missing_tools = 1);
my $dsreg  = can_run('dsreg')  or (warn "Can't find dsreg"  and $missing_tools = 1);

if ($missing_tools) {
    warn("Can't find required tools.");
    exit ($PS_EXIT_CONFIG_ERROR);
}

my $ipprc = PS::IPP::Config->new(); # IPP Configuration

my $outputDataStoreRoot = metadataLookupStr($ipprc->{_siteConfig}, 'DATA_STORE_ROOT');
exit ($PS_EXIT_CONFIG_ERROR) unless defined $outputDataStoreRoot; # lookup failure outputs a message

if (!$dbserver) {
    $dbserver = metadataLookupStr($ipprc->{_siteConfig}, 'PS_DBSERVER');
}

if ($product eq "NULL") {
    # parsing failed just with fault = 0 (this leaves previously set fault in place
    stop_request($req_id, 0, $verbose);
    exit 0;
}
if (0) {
my $prod_dir = "$outputDataStoreRoot/$product";
if (! -e $prod_dir ) {
    # something must have gone wrong at the parse stage
    stop_request($req_id, $PS_EXIT_SYS_ERROR, $verbose);
    die "product directory does not exist $prod_dir";
}
my $outdir = "$prod_dir/$req_name";
}
if (! -e $outdir ) {
    # something must have gone wrong at the parse stage
    print STDERR "output fileset directory $outdir does not exist\n" if $verbose;
    if (! mkdir $outdir ) {
        stop_request($req_id, $PS_EXIT_SYS_ERROR, $verbose);
        die "cannot create output directory $outdir";
    }
} elsif (! -d $outdir) {
    stop_request($req_id, $PS_EXIT_SYS_ERROR, $verbose);
    die "output fileset directory $outdir exists but is not a directory";
}


my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files

my $request_fault = 0;
my @jobs;
{
    my $command = "$pstamptool -listjob -req_id $req_id";
    $command .= " -dbname $dbname" if $dbname;
    $command .= " -dbserver $dbserver" if $dbserver;
    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
        run(command => $command, verbose => $verbose);
    unless ($success) {
        die("Unable to perform $command error code: $error_code");
    }
    my $output = join "", @$stdout_buf;
    if (!$output) {
        if ($verbose) {
            print STDERR "Request $req_id produced no jobs.\n";
        }
        # assume that the parser set the fault
    } else {
        my $metadata =  $mdcParser->parse($output) or die("Unable to parse metdata config doc for jobs list");
        my $jobs = parse_md_list($metadata);
        @jobs = @$jobs;
    }
}

# XXX: have the jobs produce the reglist as with postage stamp requests
my ($REGLIST, $reg_list) = tempfile("$outdir/reqlist.XXXX", UNLINK => !$save_temps);

foreach my $job (@jobs) {
    my $job_id = $job->{job_id};
    my $response_file = "response${job_id}.fits";
    my $response_path = "$outdir/$response_file";

    if (-e $response_path) {
        # the job generated a response file put it into the Data Store
        print $REGLIST "$response_file|||table|\n";

	# do the same if we have an error file.  Should the parse data be uploaded as well?
	my $err_file = "parse_error.txt";
	if (-e "$outdir/$err_file") {
	    print $REGLIST "$err_file|||text|\n";
	}
    } else  {
        print STDERR "detect_query response file for job $job_id not found\n" if $verbose;
        $request_fault = $PS_EXIT_UNKNOWN_ERROR;
    }
}
close $REGLIST;

if (-s $reg_list) {
    my $command = "$dsreg --add $req_name --product $product --list $reg_list";
    $command .= " --copy --datapath $outdir";
    $command .= " --type MOPS_DETECTABILITY_RESPONSE";
    $command .= " --ps0 $req_id";
    $command .= " --dbname $dbname" if $dbname;

    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
        run(command => $command, verbose => $verbose);
    unless ($success) {
        $request_fault = $error_code >> 8;
        print STDERR "Unable to perform $command return code: $request_fault";
        # fall through to call stop request
    }
}

stop_request($req_id, $request_fault, $verbose);

exit 0;

sub stop_request {
    my $req_id = shift;
    my $fault = shift;
    my $verbose = shift;
    
    my $command = "$pstamptool -updatereq -req_id $req_id -set_state stop";
    $command   .= " -set_fault $fault" if $fault;
    $command   .= " -dbname $dbname" if $dbname;
    $command   .= " -dbserver $dbserver" if $dbserver;
    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
        run(command => $command, verbose => $verbose);
    unless ($success) {
        die("Unable to perform $command error code: $error_code");
    }
}
