#!/bin/env perl

# Run diff_skycell.pl for a previously run diff_skyfile.
# The parameters are obtained from the diffSkyfile table database so it must not be reverted prior
# to running this script.
# if the --update argument is supplied we revert the diffSkyfile before running the command.
# if --update is not supplied we simply re-run the command and leave the database unmodified.
# WARNING: This script depends on the existing diff.skyfile.run task and diff_skycell.pl.
# If they are changed this script may need to be modified
#

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, $pretend);

my $dbname = "gpc1";
my ($diff_id, $skycell_id, $threads, $update, $no_redirect, $outdir);
my $zaplog;

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

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


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

# find warp warp diffs that have a cleaned magicDSRun
my $query1 = "SELECT path_base, diff_skyfile_id,bothways,reduction,diff_mode, diffSkyfile.fault FROM diffRun JOIN diffSkyfile USING(diff_id)  JOIN diffInputSkyfile USING(diff_id, skycell_id) WHERE diff_id = $diff_id AND skycell_id = '$skycell_id'";

my $stmt1 = $dbh->prepare($query1);
$stmt1->execute();
my $results = $stmt1->fetchrow_hashref();
my $path_base = $results->{path_base};
my $diff_skyfile_id = $results->{diff_skyfile_id};
my $bothways = $results->{bothways};
my $reduction = $results->{reduction};
my $fault = $results->{fault};

die "cannot update when skycell is not faulted\n" if $update and !$fault;

die "path_base not found\n" if !$path_base;
die "diff_skyfile_id\n" if !$path_base;

if ($outdir) {
    if ($outdir eq '.') {
        $outdir = $ENV{PWD};
    }
    my $base = basename($path_base);
    $path_base = "$outdir/$base";
}

my $command = "diff_skycell.pl --diff_id $diff_id --skycell_id $skycell_id --diff_skyfile_id $diff_skyfile_id --outroot $path_base --run-state new";

$command .= " --redirect-output" unless $no_redirect;
$command .= " --no-update" unless $update;
$command .= " --verbose" unless $no_verbose;
$command .= " --dbname $dbname" if $dbname;
$command .= " --inverse" if $bothways;
$command .= " --reduction $reduction" if $reduction;
$command .= " --threads $threads" if $threads;
$command .= " --zaplog" if $zaplog;

print "command to process this skycell\n";
print "$command\n";

exit 0 if $pretend;

if ($update) {
    my $revert_command = "difftool -revertdiffskyfile -diff_id $diff_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;
        }
    }
}


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

rundiffskyfile.pl - gather the parameters for and execute diff_skycell.pl

=head1 SYNOPSIS
    
    perl rundiffskyfile.pl --diff_id <diff_id> --skycell_id <skycell_id> [--threads <num_threads>] [--update] [--no-redirect-output] [--pretend] [--dbname <dbname>]

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

=over 4

=item * --diff_id <diff_id>

The id of the diffSkyfile run to process.

=item * --skycell_id <skycell_id>

The skycell_id of the diffSkyfile 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 diff stage turned off or the
label of this diffRun ommited from the list of labels otherwise it may attempt to processes this run at the same time.
Optional.

=item *  --no-redirect-output

Don't redirect script output to logfile. 
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
