#!/bin/env perl
###
### pstampparser_run.pl
###     Run the postage stamp request parser for a given request id
###

use warnings;
use strict;

use Sys::Hostname;
my $host = hostname();
print "\n\n";
print "Starting script $0 on $host\n\n";

if (@ARGV != 1) {
    die "usage: $0 request_id\n";
}

my $request_id = $ARGV[0];


use IPC::Cmd 0.36 qw( can_run run );

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

use PS::IPP::Config qw($PS_EXIT_SUCCESS
		       $PS_EXIT_UNKNOWN_ERROR
		       $PS_EXIT_SYS_ERROR
		       $PS_EXIT_CONFIG_ERROR
		       $PS_EXIT_PROG_ERROR
		       $PS_EXIT_DATA_ERROR
		       $PS_EXIT_TIMEOUT_ERROR
		       metadataLookupStr
		       metadataLookupBool
		       caturi
		       );

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

#my $outputDataStoreRoot = "/var/www/html/ds/dsroot";

my $outputDataStoreRoot = metadataLookupStr($ipprc->{_siteConfig}, 'PSTAMP_DATA_STORE_ROOT');
exit ($PS_EXIT_CONFIG_ERROR) unless defined $outputDataStoreRoot;
my $defaultOutputRoot = $outputDataStoreRoot;


#my $inputWorkdir = "/export/data1/bills/pstamp/work/$request_id";

my $inputWorkdir = metadataLookupStr($ipprc->{_siteConfig}, 'PSTAMP_WORKDIR');
exit ($PS_EXIT_CONFIG_ERROR) unless defined $inputWorkdir;
$inputWorkdir .= "/$request_id";
    
my $missing_tools;

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

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

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

my $psrequest;
#Look up the uri for the given request
{
    my $command = "$pstamptool -pendingreq -req_id $request_id";
    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
        run(command => $command, verbose => 1);
    unless ($success) {
        die("Unable to perform $command error code: $error_code");
    }

    if (@$stdout_buf == 0) {
        print STDERR "pending pstamp request id $request_id not found\n";
        exit 1;
    }
    my $metadata = $mdcParser->parse(join "", @$stdout_buf) or
        die("Unable to parse metdata config doc");

    my $requests = parse_md_list($metadata);

    $psrequest = ${@$requests}[0];
}

if (!$psrequest) {
    print STDERR "postage stamp request $request_id not found\n";
    # TODO: is this always an error, what if the request is no longer pending?
    exit 1;
}

my $uri = $psrequest->{uri};

# if the uri is remote, download it 
# XXX how can we tell?
# perhaps assume remote if the uri begins with http: 
# or perhaps assume it is remote if it doesn't begin with '/' or path://
# actually since we're using dsget which is an http program the former is the
# way to go. Now it's easier than that, we can assume that dsget is needed if
# request->{ds_id} != 0

my $ds_id = $psrequest->{ds_id};

if ($ds_id) {
    mkdir $inputWorkdir;
    {
        my $new_uri = "$inputWorkdir/request.fits";
        my $command = "$dsget --uri $uri --filename $new_uri";
        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
            run(command => $command, verbose => 1);
        unless ($success) {
            die("Unable to perform $command error code: $error_code");
        }

        $uri = $new_uri;
    }
}

#  create the output diredtory
my $outdir;
if ($ds_id) {
    my $command = "$pstamptool -datastore -ds_id $ds_id";
    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
        run(command => $command, verbose => 1);
    unless ($success) {
        die("Unable to perform $command error code: $error_code");
    }

    if (@$stdout_buf == 0) {
        print STDERR "data store with data store id $ds_id not found\n";
        exit 1;
    }
    my $metadata = $mdcParser->parse(join "", @$stdout_buf) or
        die("Unable to parse metdata config doc");

    my $dataStores = parse_md_list($metadata);

    my $dataStore = ${@$dataStores}[0];

    $outdir = "$outputDataStoreRoot/$psrequest->{outFileset}";
} else {
    $outdir = "$defaultOutputRoot/$psrequest->{outFileset}";
}

if (! -e $outdir ) {
    mkdir $outdir or die("unable to create output directory $outdir");
} elsif (! -d $outdir) {
    die("file with name of output directory $outdir exists but is not a directory");
}

# run pstampparse to parse the queue the jobs for this request
{
    my $command = "$pstampparse -mode queue_job -req_id $request_id -out_dir $outdir $uri";
    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
        run(command => $command, verbose => 1);
    unless ($success) {
#        die("Unable to perform $command error code: $error_code");
        if (!open OUT, ">$outdir/parse_error") {
            die("unable to open parse_error file $outdir/parse_error");
        }
        print OUT "@$stderr_buf";
        close(OUT);
    }
}

# XXX make sure that a job got actually got queued. If not set the request result and set state to
# run so that the "request finisher" can build the results file.

#
# update the state of this request from 'new' to 'run'
#
{
    my $command = "$pstamptool -processedreq -req_id $request_id -state run";
    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
        run(command => $command, verbose => 1);
    unless ($success) {
        die("Unable to perform $command error code: $error_code");
    }
}

exit 0;
