#!/usr/bin/env perl

#
# Copy diff outputs to the current directory
#

use warnings;
use strict;

use Carp;
use DBI;
use constant DB_SOCKET => '/var/run/mysqld/mysqld.sock'; # Socket for mysql
use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );

# List of products
use constant PRODUCTS => { 'REGULAR' => [ 'IMAGE', 'MASK', 'VARIANCE',
                                          'SOURCES', 'PSF', 'JPEG1', 'JPEG2',
                                          'KERNEL', 'LOG', 'STATS', ],
                           'ALL' => [ 'IMAGE', 'MASK', 'VARIANCE',
                                      'SOURCES', 'PSF', 'JPEG1', 'JPEG2', 'KERNEL',
                                      'INVERSE.IMAGE', 'INVERSE.MASK', 'INVERSE.VARIANCE', 'INVERSE.SOURCES',
#                                      'INCONV.IMAGE', 'INCONV.MASK', 'INCONV.VARIANCE',
#                                      'REFCONV.IMAGE', 'REFCONV.MASK', 'REFCONV.VARIANCE',
                                      'LOG', 'STATS',
                               ],
                           'INVERSE' => [ 'INVERSE.IMAGE', 'INVERSE.MASK',
                                          'INVERSE.VARIANCE',
                                          'INVERSE.SOURCES',
                                          'LOG', 'STATS',],
                       };

# Extensions to add to path_base
use constant EXTENSIONS => { 'IMAGE' => '.fits', # Image
                             'MASK' => '.mask.fits', # Mask
                             'VARIANCE' => '.wt.fits', # Variance
                             'SOURCES' => '.cmf', # Sources
                             'PSF' => '.psf',     # PSF
                             'JPEG1' => '.b1.jpg', # Binned JPEG
                             'JPEG2' => '.b2.jpg', # Binned JPEG
                             'KERNEL' => '.subkernel', # Convolution kernel
                             'INVERSE.IMAGE' => '.inv.fits', # Image
                             'INVERSE.MASK' => '.inv.mask.fits', # Mask
                             'INVERSE.VARIANCE' => '.inv.wt.fits', # Variance
                             'INVERSE.SOURCES' => '.inv.cmf', # Sources
                             'INCONV.IMAGE' => '.inConv.fits', # Convolved input image
                             'INCONV.MASK' => '.inConv.mk.fits', # Convolved input mask
                             'INCONV.VARIANCE' => '.inConv.wt.fits', # Convolved input variance
                             'REFCONV.IMAGE' => '.refConv.fits', # Convolved reference image
                             'REFCONV.MASK' => '.refConv.mk.fits', # Convolved reference mask
                             'REFCONV.VARIANCE' => '.refConv.wt.fits', # Convolved reference variance
                             'LOG' => '.log', # Log file
                             'STATS' => '.stats', # Statistics file
                         };

# Products that get magicked
use constant MAGIC => { 'IMAGE' => 1,
                        'MASK' => 1,
                        'VARIANCE' => 1,
                        'SOURCES' => 1,
                        'INVERSE.IMAGE' => 1,
                        'INVERSE.MASK' => 1,
                        'INVERSE.VARIANCE' => 1,
                        'INVERSE.SOURCES' => 1,
};


my ($db_host, $db_name, $db_user, $db_pw); # Database details
my ($diff_id, $skycell_id);     # Diff and skycell of interest
my ($input);                    # Input list
my ($products);                 # Products of interest
my ($muggle);                   # Not magicked?

GetOptions(
           'dbhost=s' => \$db_host, # Database host name
           'dbname=s' => \$db_name, # Database name
           'dbuser=s' => \$db_user, # Database user
           'dbpass=s' => \$db_pw, # Database p/w
           'diff_id=s' => \$diff_id, # Diff identifier
           'skycell_id=s' => \$skycell_id, # Skycell identifier
           'products=s' => \$products, # Products of interest
           'muggle'   => \$muggle, # Not magicked?
           ) or die "Unable to parse arguments.\n";
die "Unknown option: @ARGV\n" if @ARGV;
die "Required options: --dbhost --dbname --dbuser --dbpass --diff_id\n"
    unless defined $db_host
    and defined $db_name
    and defined $db_user
    and defined $db_pw
    and defined $diff_id;

# Database connection
my $db = DBI->connect( "DBI:mysql:database=$db_name;host=$db_host;mysql_socket=" . DB_SOCKET(),
                       $db_user,
                       $db_pw,
                       { RaiseError => 1, AutoCommit => 1 }
                       ) or die "Unable to connect to database: $DBI::errstr";


# Query to run
my $sql = "SELECT path_base, bothways FROM diffSkyfile JOIN diffRun USING(diff_id) WHERE diff_id = $diff_id AND fault = 0 AND quality = 0";
$sql .= " AND skycell_id = '$skycell_id'" if defined $skycell_id;

# List of diffs
my $diffs = $db->selectall_arrayref( $sql, { Slice => {} }
                                     ) or die "Unable to execute SQL: $DBI::errstr";

my @products;                   # Array of products
if (defined $products) {
  PRODUCT_SEARCH: foreach my $product ( split(/,/, $products) ) {
      foreach my $key ( keys %{PRODUCTS()} ) {
          if ($product eq $key) {
              push @products, @{${PRODUCTS()}{$key}};
              next PRODUCT_SEARCH;
          }
      }
      push @products, $product;
  }
} else {
    @products = @{${PRODUCTS()}{'ALL'}};
}

foreach my $diff ( @$diffs ) {
    foreach my $product ( @products ) {
        next if (not defined $diff->{bothways} or $diff->{bothways} eq 'NULL' or not $diff->{bothways}) and $product =~ /INVERSE/;
        my $path = $diff->{path_base};
        if (defined $muggle and defined ${MAGIC()}{$product}) {
            my @path = split /\//, $path;
            my $last = pop @path;
            push @path, "SR_$last";
            $path = join '/', @path;
        }
        copy_extension( $path, ${EXTENSIONS()}{$product} );
    }
}


# Pau.


sub copy_extension
{
    my $path = shift;           # Path to copy
    my $ext = shift;            # Extension to copy

    my $file = "$path$ext";     # File
    my $source = `ipp_datapath.pl $file` or (carp "Unable to locate $file\n" and return); # Actual file
    chomp $source;
    my ($target) = $source =~ m|^.*[:/](.*)|; # Target name
    !system "cp $source $target" or carp "Unable to copy $source\n";
}
