#!/usr/bin/env perl

# Read and parse a fits table containing a MOPS_DETECTABILITY_QUERY Extension
# and optionally print out the contents

# by default prints out the keywords in the exension header followed by the rows of the table
# with labels
# -l omits the labels
# -h omits the header
# -r omits the rows
# so -lhr will print nothing

use warnings;
use strict;

use Astro::FITS::CFITSIO qw( :constants );
Astro::FITS::CFITSIO::PerlyUnpacking(1);
use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
use Pod::Usage qw( pod2usage );
use Math::Trig;
use Data::Dumper;

use constant EXTNAME => 'MOPS_DETECTABILITY_QUERY'; # Extension name for table

my $no_print_label  = 0;    # omit the labels
my $no_print_header = 0;    # omit the header keywords
my $no_print_rows   = 0;    # omit the rows


my ( $input,			# Name of input text file
     $output,			# Name of output table
     $save_temps,		# Save temporary files?
     );

GetOptions(
	   'input|i=s'    => \$input,
	   'output|o=s'   => \$output,
           'nolabel|l'    => \$no_print_label,
           'noheader|h'   => \$no_print_header,
           'norows|r'     => \$no_print_rows
) or pod2usage( 2 );

pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
pod2usage( -msg => "Required options: --input",
           -exitval => 3) unless defined $input;

if ($output && ($output ne "-")) {
    die "cannot open $output for output\n" unless open OUTFILE, ">$output";
    select OUTFILE;
}

my $status = 0;

# The required keywords
my $header = {
        'QUERY_ID' => { name => 'QUERY_ID', 
                        writetype => TSTRING, 
                        comment => 'MOPS Query ID for this batch query',
                        value => undef
                      },
        'FPA_ID'   => { name => 'FPA_ID', 
                        writetype => TSTRING, 
                        comment => 'orginal FPA_ID used at ingest',
                        value => undef
                      }, 
        'MJD_OBS'  => { name => 'MJD-OBS', 
                        writetype => TDOUBLE, 
                        comment => 'starting time of the exposure, MJD',
                        value => undef
                      },
        'FILTER'   => { name => 'FILTER', 
                        writetype => TSTRING, 
                        comment => 'effective filter use for the exposure',
                        value => undef
                      },
        'OBSCODE'  => { name => 'OBSCODE', 
                        writetype => TSTRING, 
                        comment => 'site identifier (MPC observatory code)',
                        value => undef
              }
};

# key_array insures that the order that the keywords is printed out is
# the same as the ICD
my @key_array = qw( QUERY_ID FPA_ID MJD_OBS FILTER OBSCODE );

# Specification of columns
my $column_defs = [ 
        # matching rownum from detectability original request
        { name => 'ROWNUM',   type => '20A', writetype => TSTRING }, 
        # coordinate at start of exposure, in degrees
        { name => 'RA1_DEG',  type => 'D',   writetype => TDOUBLE },
        # coordinate at start of exposure, in degrees
        { name => 'DEC1_DEG', type => 'D',   writetype => TDOUBLE },
        # coordinate at end of exposure, in degrees
        { name => 'RA2_DEG',  type => 'D',   writetype => TDOUBLE },
        # coordinate at end of exposure, in degrees
        { name => 'DEC2_DEG', type => 'D',   writetype => TDOUBLE },
        # apparent magnitude
        { name => 'MAG',      type => 'D',   writetype => TDOUBLE },
];

# Parse the list of columns
my @colNames;			# Names of columns
my @colTypes;			# Types of columns
my @colWriteType;               # type to use to write
my %colData;			# Data for each column referenced by name
foreach my $colSpec ( @$column_defs) {
    push @colNames, $colSpec->{name};
    push @colTypes, $colSpec->{type};
    push @colWriteType, $colSpec->{writetype};
}

# Read the input file

my $inFits = Astro::FITS::CFITSIO::open_file( $input, READONLY, $status ); # FITS file handle
check_fitsio($status);

$inFits->movnam_hdu(BINARY_TBL, EXTNAME, 0, $status) and check_fitsio($status);

my $inHeader = $inFits->read_header(); # Header for input

my $numRows;			# Number of rows in table
$inFits->get_num_rows($numRows, $status) and check_fitsio($status);

foreach my $col (@$column_defs) {
    my ($col_num, $col_type, $col_data);

    $inFits->get_colnum(0, $col->{name}, $col_num, $status) and check_fitsio($status);
    $inFits->get_coltype($col_num, $col_type, undef, undef, $status) and check_fitsio($status);
    $inFits->read_col($col_type, $col_num, 1, 1, $numRows, 0, $col_data, undef, $status)
                                                                    and check_fitsio($status);
    $colData{$col->{name}} = $col_data;
}

# Now produce the output

if (!$no_print_header) {
    my $label;
    my $data;
    # I don't do this because I want the keys to be printed in a particular order
    #foreach my $key (keys %$header) {
    foreach my $key (@key_array) {
        my $name = $header->{$key}->{name};
        my $value = $inHeader->{$name};
        # get rid of quotes and whitespace
        $value =~ s/\'//g;
        if (defined $value) {
            #print "$key\t\t\t$value\n";
            $label .= sprintf "%-12s ", $key;
            $data  .= sprintf "%-12s ", $value;
        } else {
            die "keyword $key not found in $input\n";
        }
    }
    print "# " . $label . "\n" unless $no_print_label;
    print $data  . "\n";
}

if (!$no_print_rows) {
    if (!$no_print_label) {
        print "# ";
        foreach my $col (@$column_defs) {
            printf "%-12s ", $col->{name};
        }
        print "\n";
    }

    for (my $i = 0; $i < $numRows; $i++) {
        foreach my $col (@$column_defs) {
            printf "%-12s ", $colData{$col->{name}}->[$i];
        #foreach my $aref (@col_arrays) {
            #printf "%-12s ", $aref->[$i];
        }
        print "\n";
    }
}

exit 0;

### Pau.

# From Astro::FITS::CFITSIO demo
sub check_fitsio
{
    my $status = shift;		# Status of FITSIO calls

    if ($status != 0) {
	my $msg;		# Message to output
	Astro::FITS::CFITSIO::fits_get_errstatus( $status , $msg );
	die "CFITSIO error: $msg\n";
    }
}

__END__
