#!/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 ($first, $last, $stage, $alt_workdir, $no_verbose);

my $dbname = "gpc1";
my ($warp_id, $skycell_id, $threads, $update, $redirect, $pretend, $save_temps, $outdir);
my $zaplog;

GetOptions(
    'warp_id=i'         => \$warp_id,
    'skycell_id=s'      => \$skycell_id,
    'threads=i'         => \$threads,
    'pretend'           => \$pretend,
    'zaplog'            => \$zaplog,
    'redirect-output'   => \$redirect,
    'outdir=s'          => \$outdir,
    'update'            => \$update,
    'dbname=s'          => \$dbname,
    'no-verbose'        => \$no_verbose, 
    'save-temps'        => \$save_temps,
) or pod2usage( 2 );

pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
pod2usage( -msg => "--warp_id and --skycell_id are required", -exitval => 2 )
    if !$warp_id or !$skycell_id;

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

my $query1 = "SELECT warpSkyfile.path_base, warpSkyfile.fault, warp_skyfile_id, warpRun.tess_id, warpRun.reduction, chipRun.magicked, rawExp.camera, warpRun.state FROM warpRun JOIN warpSkyfile USING(warp_id) JOIN warpImfile USING(warp_id, skycell_id) JOIN fakeRun USING(fake_id) JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) WHERE warp_id = $warp_id AND skycell_id = '$skycell_id'";

my $stmt1 = $dbh->prepare($query1);
$stmt1->execute();
my $results = $stmt1->fetchrow_hashref();
die "query returned no results\n" if !$results;
my $path_base = $results->{path_base};
my $warp_skyfile_id = $results->{warp_skyfile_id};
my $tess_id = $results->{tess_id};
my $reduction = $results->{reduction};
my $magicked = $results->{magicked};
my $camera = $results->{camera};
my $state = $results->{state};
my $fault = $results->{fault};

die "cannot update database for a skycell that is not faulted\n" if $update and !$fault;

die "path_base not found\n" if !$path_base;
die "warp_skyfile_id not found\n" if !$warp_skyfile_id;
die "tess_id not found\n" if !$tess_id;
die "magicked not found\n" if ! defined $magicked;
die "camera not found\n" if !$camera;
die "state not found\n" if !$state;

my  $run_state;
if ($state eq 'full' or $state eq 'new') {
    $run_state = 'new';
} elsif ($state eq 'update') {
    $run_state = 'update';
    # If the input chipRun has magicked < 0 we do not proceed because we don't know the magicked state of the inputs
    # The warptool -towarped query gets the right magicked value from the chipProcessedImfiles. Our simple query
    # does not and I'm not going to bother doint that today.
    die "chipRun is not fully destreaked. This script does not support this state\n" if !$pretend and $magicked < 0;
} else {
    die "unexpected warpRun.state found: $state\n";
}

if ($outdir) {
    my $base = basename($path_base);
    $path_base = "$outdir/$base";
    print "changing path_base to $path_base\n";
}

my $command = "warp_skycell.pl --warp_id $warp_id --skycell_id $skycell_id --warp_skyfile_id $warp_skyfile_id --outroot $path_base --run-state $run_state --tess_dir $tess_id --camera $camera" ;

$command .= " --magicked $magicked" if $magicked > 0;
$command .= " --reduction $reduction" if $reduction and ($reduction ne "NULL");
$command .= " --redirect-output" if $redirect;
$command .= " --save-temps" if $save_temps;
$command .= " --no-update" unless $update;
$command .= " --verbose" unless $no_verbose;
$command .= " --dbname $dbname" if $dbname;
$command .= " --zaplog" if $zaplog;

if ($update) {
    my $revert_command = "warptool -revertwarped -warp_id $warp_id -skycell_id $skycell_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 skycell\n";
print "$command\n";

exit 0 if $pretend;

my $rc =  system $command;
exit $rc >> 8;


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

runwarpskyfile.pl - gather the parameters for and execute warp_skycell.pl

=head1 SYNOPSIS
    
    perl runwarpskyfile.pl --warp_id <warp_id> --skycell_id <skycell_id> [--threads <num_threads>] [--update] [--redirect-output] [--pretend] [--dbname <dbname>]

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

=over 4

=item * --warp_id <warp_id>

The id of the warpSkyfile run to process.

=item * --skycell_id <skycell_id>

The skycell_id of the warpSkyfile run to process.

=item * --threads <num_threads>

The number of threads to use. Default 1.
Optional.


=item * --update

Revert a faulted skycell before processing. If the skycell is not faulted no processing is done.
WARNING: insure that the standard science procesing either has warp stage turned off or the
label of this warpRun ommited from the list of labels otherwise it may attempt to processes this run at the same time.
Optional.

=item *  --redirect-output

Send the output of the command to the logfile. (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 * --dbname <dbname>

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


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

=cut
