#!/usr/bin/env perl

use strict;
use warnings;

use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
use Pod::Usage qw( pod2usage );
use File::Basename;


my $joinType = '1and2';
my $in;
my $out;
my $jardir = $ENV{JARDIR};

$jardir = '/home/panstarrs/bills/jars' unless $jardir;

my $stiltsJar = "$jardir/stilts.jar";
my $stilts = "java -jar $stiltsJar";

my $testdata;

my ($verbose, $save_temps);

GetOptions(
    "testdata=s"        =>  \$testdata,
    "join=s"            =>  \$joinType,
    "verbose|v"         =>  \$verbose,
    "save-temps"        =>  \$save_temps,
) or pod2usage( 2 );

die "usage: $0 <stack batch file> <out> [--testdata <location of testdata directory]\n" unless (scalar @ARGV == 2);

$in = shift;
$out = shift;

my $command;

my $base = basename($in);

my @filters = qw(none g r i z y);

# Find the stack_ids for the various filters
$command = "$stilts tpipe in=$in'#StackObjectAttributes' cmd='keepcols \"gstackImageID rStackImageID iStackImageID zstackImageID ystackImageID\";stats Maximum;' ofmt=ascii";

print "$command\n" if $verbose;
my $stackList = `$command`;
die "Failed to find stack_ids from $in\n" unless $stackList;

my @stackIDs = split "\n", $stackList;
# shift off the header row
# shift @stackIDs;

my @cmfs;
if ($testdata) {
    for (my $i=1; $i<=5; $i++) {
        my $stack_id = $stackIDs[$i];
        my $cmf = 'none';
        if ($stack_id > 0) {
            $cmf = sprintf "%s/stack.%02d.cmf", $testdata, $stack_id;
        }
        $cmfs[$i] = $cmf;
        print "$filters[$i] $stack_id $cmf\n" if $verbose;
    }
} else {
    # XXX: look up the cmf for this stack here
    die "this program only works in test mode right now\n";
}


my $outfile;
my $input = $in;
for (my $i=1; $i<=5; $i++) {
    my $cmf = $cmfs[$i];
    next if $cmf eq 'none';

    my $filter = $filters[$i];
    my $ippjoined = $filter . "_joined" . basename($cmf);

    $command = "joinstackcmf $cmf $ippjoined";
    $command .= " --ofmt fits";
    $command .= " --test" if $testdata;

    runcommand($command);

    my $stackColumn = $filter . "stackImageID";
    my $idColumn    = $filter . "ippDetectID";
    $outfile = $filter . "_matched" . basename($cmf);

    $command = "$stilts tmatch2 in1=$input'#StackObjectAttributes' in2=$ippjoined matcher=2d out=$outfile ofmt=fits"
        . " values1='$stackColumn $idColumn' values2='STACK_ID IPP_IDET' params=.01 join=$joinType"
        . " fixcols=all suffix1='' suffix2=_$filter ocmd='tablename StackObjectAttributes'"
        . " progress=none";
    runcommand($command);

    if (!$save_temps) {
        unlink $ippjoined;
        if ($input ne $in) {
            unlink $input;
        }
    }
    # input for next round of matches is the output from this one
    $input = $outfile;
}

my $list = getStackColumns();
my $cmd = "'";
# add x_zpFactor columns
for (my $i = 1; $i<=5; $i++) {
    next if $cmfs[$i] eq 'none';
    my $filter = $filters[$i];
    my $zp = $filter . "zp";
    $cmd .= "addcol -after $zp ${filter}zpFactor 3630.78*pow(10,-0.4*$zp);";
}
foreach my $line (@$list) {
    my ($col, $ipp, $conversion) = split ' ', $line;
    next if !$ipp;
    $conversion = "" unless $conversion;
    my $equation = "$ipp$conversion";
    $equation = "$col-$equation";
    my $dcol = "d_$col";
    $cmd .= "addcol -after $col $dcol $equation;";
}
$cmd .= "'";

$command = "$stilts tpipe in=$outfile out=$out cmd=$cmd";

runcommand($command);
unlink($outfile) unless $save_temps;

exit 0;

sub runcommand {
    my $command = shift;
    print "Running: $command\n" if $verbose;
    my $rc = system $command;
    if ($rc) {
        my $status = $rc >> 8;
        die "$command failed\nrc = $rc status = $status";
    }
}

# list of columns from stackObjectAttributes table
sub getStackColumns {
    my $filters = shift;
    my $cmfs = shift;

    # format of the list is "psps column"   "ipp column"    "equation to convert ipp value to psps value"
    # If equation is blank the psps column is the same as the ipp column
    # columns which begin in x_ have a different value for each of the 5 filters
    # similarly ipp columns that end in _x have the name col_$filter

    my $list = <<END_OF_LIST;
# Note x_zpFactor = 3630.78*pow(10, -0.4*x_zp)

objID
uniquePspsSTid
ippObjID
randomStackObjID
stackDetectRowID
primaryDetection
bestDetection

x_ippDetectID     IPP_IDET
x_stackDetectID
x_stackImageID    STACK_ID
x_xPos            X_PSF
x_yPos            Y_PSF
x_xPosErr         X_PSF_SIG
x_yPosErr         Y_PSF_SIG
x_psfMajorFWHM    PSF_FWHM_MAJ            *abs(PLTSCALE_x)
x_psfMinorFWHM    PSF_FWHM_MIN            *abs(PLTSCALE_x)
x_psfTheta        PSF_THETA
x_psfCore         PSF_CORE
x_psfLikelihood                                                 # actually psfLikelihood(EXT_NSIGMA). We assume the formula is ok.
x_psfQf           PSF_QF
x_psfQfPerfect    PSF_QF_PERFECT
x_psfChiSq        PSF_CHISQ
x_momentXX        MOMENTS_XX		*PLTSCALE_x*PLTSCALE_x
x_momentXY        MOMENTS_XY		*PLTSCALE_x*PLTSCALE_x
x_momentYY        MOMENTS_YY		*PLTSCALE_x*PLTSCALE_x
x_momentR1        MOMENTS_R1            *abs(PLTSCALE_x)
x_momentRH        MOMENTS_RH            *sqrt(abs(PLTSCALE_x))

x_psfFlux         PSF_INST_FLUX 	*x_zpFactor/x_expTime
x_psfFluxErr      PSF_INST_FLUX_SIG	*x_zpFactor/x_expTime

x_apFlux          AP_FLUX		*x_zpFactor/x_expTime
x_apFluxErr       AP_FLUX_SIG		*x_zpFactor/x_expTime
x_apFillFac       AP_NPIX               /(3.14159265359*pow(AP_MAG_RADIUS_x-0.5,2))
x_apRadius        AP_MAG_RADIUS         *abs(PLTSCALE_x)
x_KronFlux        KRON_FLUX		*x_zpFactor/x_expTime
x_KronFluxErr     KRON_FLUX_ERR		*x_zpFactor/x_expTime
x_KronRad         MOMENTS_R1            *2.5*abs(PLTSCALE_x)
x_expTime
x_ExtNSigma       EXT_NSIGMA
x_sky             SKY                   /PLTSCALE_x/PLTSCALE_x*x_zpFactor/x_expTime
x_skyErr          SKY_SIGMA             /PLTSCALE_x/PLTSCALE_x*x_zpFactor/x_expTime
x_zp
x_PlateScale      PLTSCALE
END_OF_LIST

    my @lines = split "\n", $list;

    my @output;
    foreach my $l (@lines) {
        # skip comment lines and empty lines
        next if $l =~ '^#';
        next if !$l;
        # strip off trailing comment
        my ($data, $comment) = split '#', $l;
        my ($column, $ippColumn, $equation) = split " ", $data;

        $ippColumn = "" unless $ippColumn;
        $equation  = "" unless $equation;
        if ($column =~ '^x_') {
            for (my $i=1; $i<=5; $i++) {
                my $c = $cmfs[$i];
                next if $c eq 'none';
                my $f = $filters[$i];
                my $newCol = $f . substr($column, 2);
                my $newIpp = "";
                if ($ippColumn) {
                    $newIpp = $ippColumn . "_$f";
                }
                my $newEquation = $equation;
                $newEquation =~ s/_x/_$f/g;
                $newEquation =~ s/x_/$f/g;
                my $newline = sprintf "%s\t%s\t%s", $newCol, $newIpp, $newEquation;
                # print "$newline\n";
                push @output, $newline;
            }
        } else {
            # print "$l\n";
            push @output, $l;
        }
        
    }

    return \@output;
}

