#!/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 ($chip_id, $class_id, $threads, $update, $redirect, $pretend, $save_temps, $outdir);

my $zaplog;

GetOptions(
    'chip_id=i'         => \$chip_id,
    'class_id=s'      => \$class_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 => "--chip_id and --class_id are required", -exitval => 2 )
    if !$chip_id or !$class_id;

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

my $query1 = "SELECT chipProcessedImfile.path_base, camera, exp_id, rawImfile.magicked AS raw_magicked, (rawImfile.user_1 is not NULL and rawImfile.user_1 > 0.5)  As deburned, chip_imfile_id, chipProcessedImfile.fault, rawImfile.uri, chipRun.reduction, chipRun.state";
$query1 .= " FROM chipRun join chipProcessedImfile using(chip_id,exp_id) JOIN chipImfile USING (chip_id, class_id) JOIN rawExp using(exp_id) JOIN rawImfile USING(exp_id, camera, class_id) WHERE chip_id = $chip_id AND class_id = '$class_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 $chip_imfile_id = $results->{chip_imfile_id};
my $reduction = $results->{reduction};
my $magicked = $results->{raw_magicked};
my $camera = $results->{camera};
my $state = $results->{state};
my $fault = $results->{fault};
my $uri = $results->{uri};
my $deburned = $results->{deburned};
my $exp_id = $results->{exp_id};

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

die "path_base not found\n" if !$path_base;
die "chip_imfile_id not found\n" if !$chip_imfile_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';
} else {
    die "unexpected chipRun.state found: $state\n";
}

if ($outdir) {
    my $base = basename($path_base);
    $path_base = "$outdir/$base";
}

my $command = "chip_imfile.pl --exp_id $exp_id --chip_id $chip_id --chip_imfile_id $chip_imfile_id --class_id $class_id --uri $uri --camera $camera --run-state $run_state --deburned $deburned --outroot $path_base" ;

$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;
$command .= " --threads $threads" if $threads;

if ($update) {
    my $revert_command = "chiptool -revertprocessedimfile -chip_id $chip_id -class_id $class_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 chip\n";
print "$command\n";

exit 0 if $pretend;

my $rc = system $command;
my $status = $rc >> 8;
if ($rc) {
    print STDERR "command failed with $rc $status\n";
    $status = 1 unless $status;
} else {
    print "Successfully rebuilt chip $chip_id $class_id\n";
}
exit $status;


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

runchipimfile.pl - gather the parameters for and execute chip_imfile.pl

=head1 SYNOPSIS
    
    XXX: pod TODO

    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
