#!/usr/bin/env perl

use strict;
use warnings;

use Getopt::Long;
use Pod::Usage;
use FileHandle;
use Data::Dumper;

use PS::MOPS::Constants qw(:all);
use PS::MOPS::DC::Instance;
use PS::MOPS::DC::Tracklet;
use PS::MOPS::DC::Orbit;
use PS::MOPS::JPLEPH;


use subs qw(
);


# Options.
my $inst;
my $instance_name;
my $help = 0;

# Start program here.
GetOptions(
    'instance=s' => \$instance_name,
    help => \$help,
) or pod2usage(2);
my $orbits_file = shift or die pod2usage(-message => "input not specified.");

$inst = PS::MOPS::DC::Instance->new(DBNAME => $instance_name);
my $mc = $inst->getConfig();
my $ml = $inst->getLogger();

my $line;
my $track_id;
my @stuff;
my @tids;
my $fmt;
my $classification;
my $synth_id;
my $orbit;
my $orbit_code;
my $dummy;
my $rest;
my %tracks;

my $orbits_fh = new FileHandle($orbits_file) or $ml->logdie("can't open $orbits_file");

while ($line = <$orbits_fh>) {
    next if $line =~ /^(#|!)/;      # MOPS or DES comment, skip
    if ($line =~ /^MIF-TRACK/) {
        ($dummy, $dummy, $classification, $synth_id, $orbit_code, $fmt, $track_id, $rest) = split /\s+/, $line, 8;

        if ($orbit_code eq $MOPS_EFF_ORBIT_OK) {
            # It's a good orbit so far, so check residual trends.
            $orbit = modco_deserialize($inst, "$fmt $track_id $rest");
            my $rc = analyze_residuals($orbit, @tids);
            if ($rc) {
                # Rejected. Rewrite line so that we record the failed orbit due to 
                # tracklet resids.
                print join(' ', 
                    'MIF-TRACK', $track_id,
                    $classification, $synth_id, $MOPS_EFF_ORBIT_RESIDUALS, $fmt, $track_id, $rest,
                ), "\n";
            }
            else {
                print $line;
            }
        }
        else {
            # Bad orbit to start with.
            print $line;        # just re-remit line
        }
    }
    elsif ($line =~ /^MIF-O/) {
        # This is not the normal case, where we have MIF-Os.  Include this processing
        # branch for testing on MIF-O orbit data.
        #
        ($fmt, $track_id, @stuff) = split /\s+/, $line;
        @tids = split /=/, $track_id;   # tracklet IDs from track ID
        $orbit = modco_deserialize($inst, $line);
        my $rc;
        unless ($rc) {
            print $line;        # just re-remit
        }
    }
    else {
        $ml->logdie("strange line: $line");
    }
}
$orbits_fh->close();
exit 0;


sub analyze_residuals {
    my ($orbit, @tids) = @_;
    return 0;       # until we get rules from MG

    my $trk;
    my ($k, $v);
    my ($det_id, $resid);
    my $NO_AST_REJECT = 0;
    my %rejected;           # table of rejected orbits

    while (($k, $v) = each %tracks) {
        my @dets;
        my %det2trk;
        my %detid2det;
        foreach my $tid (@{$v->{TIDS}}) {
            $trk = modct_retrieve($inst, trackletId => $tid);
            push @dets, @{$trk->detections};

            # Want to map which dets belong to which tracklets.
            $det2trk{$_->detId} = $tid foreach @{$trk->detections};
            $detid2det{$_->detId} = $_ foreach @{$trk->detections};
        }

        my $resids = jpleph_calcDetectionResiduals(
            orbit => $v->{ORBIT},
            detections_ref => \@dets,
        );
    }

    return 0;   # orbit is OK
}


=head1 NAME

analyze_tracklet_resids - generate per-detection residuals from orbit output

=head1 SYNOPSIS

analyze_tracklet_resids FOO.orbits > FOO.analyzed

=head1 DESCRIPTION

Takes a MIF-O or MIF-OC orbits file and computes per-detection residuals.  Then if
any of the tracklets contains detections where all detections deviate by more than
1-sigma from the fitted orbit, the orbit is rejected by emitting the orbit line 
with a 'R' orbit code.

=cut

