#!/bin/env perl

use strict;
use warnings;
use DBI;
use IPC::Cmd 0.36 qw( can_run run );
use PS::IPP::Metadata::Config;
use PS::IPP::Config 1.01 qw( :standard );

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


my $dbname = "gpc1";
my ($stack_id, $threads, $update, $redirect, $pretend, $no_verbose);

GetOptions(
    'stack_id=i'        => \$stack_id,
    'threads=i'         => \$threads,
    'pretend'           => \$pretend,
    'redirect-output'   => \$redirect,
    'update'            => \$update,
    'dbname=s'          => \$dbname,
    'no-verbose'        => \$no_verbose, 
) or pod2usage( 2 );

pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
pod2usage( -msg => "--stack_id is required", -exitval => 2 ) if !$stack_id;

my $ipprc =  PS::IPP::Config->new();
my $dbh = getDBHandle();

my $query = "SELECT * FROM stackRun JOIN stackSumSkyfile USING(stack_id) WHERE stack_id = $stack_id";

my $stmt = $dbh->prepare($query);
$stmt->execute();
my $results = $stmt->fetchrow_hashref();
die "query returned no results\n" if !$results;

my $path_base = $results->{path_base};
my $tess_id = $results->{tess_id};
my $reduction = $results->{reduction};
my $state = $results->{state};
my $fault = $results->{fault};

die "path_base not found\n" if !$path_base;
die "tess_id not found\n" if !$tess_id;
#die "reduction not found\n" if ! defined $reduction;
die "state not found\n" if !$state;
die "fault not found\n" if !defined $fault;

die "Cannot update when run is not faulted\n" if $update and ! $fault;

my  $run_state;
if ($state eq 'full' or $state eq 'new') {
    $run_state = 'new';
} elsif ($state eq 'update') {
    die "unexpected stackRun.state found: $state\n";
}

my $command = "stack_skycell.pl --stack_id $stack_id --outroot $path_base --run-state $run_state ";

$command .= " --reduction $reduction" if $reduction and ($reduction ne "NULL");
$command .= " --threads $threads" if $threads;
$command .= " --redirect-output" if $redirect or $update;
$command .= " --no-update" unless $update;
$command .= " --verbose" unless $no_verbose;
$command .= " --dbname $dbname" if $dbname;

if ($update) {
    my $revert_command = "stacktool -revertsumskyfile -stack_id $stack_id -dbname $dbname";
    if ($pretend) {
        print "skipping $revert_command\n";
    } else {
        my $rc = system $revert_command;
        if ($rc != 0) {
            my $status = $rc >> 8;
            print STDERR "$revert_command failed: $rc $status\n";
            exit $status;
        }
    }
}
print "command to process this stackRun\n";
print "$command\n";

exit 0 if $pretend;

exit system $command;


sub getDBHandle {
    my $dbserver = metadataLookupStr($ipprc->{_siteConfig}, "DBSERVER");
    my $dbuser = metadataLookupStr($ipprc->{_siteConfig}, "DBUSER");
    my $dbpassword = metadataLookupStr($ipprc->{_siteConfig}, "DBPASSWORD");
    if (!$dbname) {
        $dbname = metadataLookupStr($ipprc->{_siteConfig}, "DBNAME");
    }

    die "database configuration set up" unless defined($dbserver) and defined($dbuser)
        and defined($dbpassword) and defined($dbname);

    my $dsn = "DBI:mysql:host=$dbserver;database=$dbname";

    my $dbh = DBI->connect($dsn, $dbuser, $dbpassword) 
        or die "Cannot connect to database.\n";

    return $dbh;
}

__END__

=pod

=head1 NAME

runstackskycell.pl - gather the parameters for and execute stack_skycell.pl

=head1 SYNOPSIS
    
    perl runstackskycell.pl --stack_id <stack_id> [--update] [--redirect-output] [--pretend] [--threads <nthreads>] [--dbname <dbname>]

Query the database for the results of a completed stack run and rerun the processing, optionally reverting a faulted
run.

=over 4

=item * --stack_id <stack_id>

The id of the stack run to process.

=item * --update

Revert a faulted run before processing. If the run is not faulted an error occurs.
WARNING: insure that the standard science processing either has stack stage turned off or the
label of this stackRun omitted from the label list otherwise it may attempt to processes this run at the same time.

Optional.

=item *  --redirect-output

Send the output of the command to the log file. (This is the default if --update is supplied).

Optional.

=item * --pretend

Just print the commands that would be executed, but do not run them.

Optional.

=item * --threads <nthrads>

Number of threads to be used by use ppStack. Default is 1 (single threaded).

Optional.

=item * --dbname <dbname>

Name of the IPP databse to query. Default is 'gpc1'.

Optional.


=head1 SEE ALSO
L<runchipimfile.pl>, L<runwarpskyfile.pl>, L<rundiffskyfile.pl>

=cut
