#!/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 ($cam_id, $update, $redirect, $save_temps, $pretend, $no_verbose);
my ($outdir, $no_masks);

GetOptions(
    'cam_id=i'          => \$cam_id,
    'pretend'           => \$pretend,
    'redirect-output'   => \$redirect,
    'save-temps'        => \$save_temps,
    'outdir=s'          => \$outdir,    # move outroot to this directory
    'no-masks'          => \$no_masks,
    'update'            => \$update,
    'dbname=s'          => \$dbname,
    'no-verbose'        => \$no_verbose, 
) or pod2usage( 2 );

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

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

my $query = "SELECT rawExp.camera, rawExp.exp_tag, camProcessedExp.path_base, camProcessedExp.fault, camRun.dvodb, camRun.reduction, camRun.state FROM camRun JOIN camProcessedExp USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id) WHERE cam_id = $cam_id";

my $stmt = $dbh->prepare($query);
$stmt->execute();
my $results = $stmt->fetchrow_hashref();
die "query returned no results\n" if !$results;
my $camera = $results->{camera};
my $exp_tag = $results->{exp_tag};
my $path_base = $results->{path_base};
my $dvodb = $results->{dvodb};
my $reduction = $results->{reduction};
my $state = $results->{state};
my $fault = $results->{fault};

die "path_base not found\n" if !$path_base;
die "exp_tag not found\n" if !$exp_tag;
die "dvodb not found\n" if !$dvodb;
die "camera not found\n" if !$camera;
die "state not found\n" if !$state;
die "reduction not found\n" if !$reduction;

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

if ($outdir) {
    if ($outdir eq ".") {
        $outdir = $ENV{PWD};
    }
    my $base = basename($path_base);
    $path_base = "$outdir/$base";
    print STDERR "changing path_base to $path_base";
    $update = 0;
}

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

my $command = "camera_exp.pl --exp_tag $exp_tag --cam_id $cam_id --camera $camera --outroot $path_base --run-state $run_state ";

$command .= " --reduction $reduction" if $reduction and ($reduction ne "NULL");
$command .= " --dvodb $dvodb" if $dvodb and ($dvodb ne "NULL");
$command .= " --redirect-output" if $redirect or $update;
$command .= " --save-temps" if $save_temps;
$command .= " --no-update" unless $update;
$command .= " --verbose" unless $no_verbose;
$command .= " --dbname $dbname" if $dbname;
$command .= " --skip-binned" if $no_masks;
$command .= " --skip-refmask" if $no_masks;



if ($update) {
    my $revert_command = "camtool -revertprocessedexp -cam_id $cam_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 camRun\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

runcameraexp.pl - gather the parameters for and execute camera_exp.pl

=head1 SYNOPSIS
    
    perl runcameraexp.pl --cam_id <cam_id> [--update] [--redirect-output] [--pretend] [--dbname <dbname>] [--no-masks]

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

=over 4

=item * --cam_id <cam_id>

The id of the camera run to process.

=item * --update

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

Optional.

=item *  --no-masks

Override the recipe values to skip production of binnned images and creation
of reference star masks. This allows psastro to perform the astrometry
analysis even if the input chipRun has been cleaned up.

Optional (for debugging).

=item *  --outdir <outdir>

Change the output root to the provided directory instead of the path_base
in the database.  

Optional.

=item *  --redirect-output

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

=item *  --save-temps

Pass -save-temps to camera_exp.pl

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<runwarpskyfile.pl>, L<rundiffskyfile.pl>

=cut
