#!/usr/bin/env perl

use strict;
use warnings;

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

use PS::MOPS::DC::Instance;
use PS::MOPS::MITI;


my $inst;
my $instance_name;
my $help;
my $summary;
my $clean;
my $mixed;
my $unfound;
my $recov_file;
GetOptions(
    'instance=s' => \$instance_name,
    summary => \$summary,
    clean => \$clean,
    mixed => \$mixed,
    unfound => \$unfound,
    'recov_file=s' => \$recov_file,
    help => \$help,
) or pod2usage(2);
pod2usage(-verbose => 2) if $help;
pod2usage(3) unless @ARGV;
$inst = PS::MOPS::DC::Instance->new(DBNAME => $instance_name);
my $mops_logger = $inst->getLogger;


my ($tracks_file) = shift;

# Read MITI output file of linkages, generated by lt2miti.
# TRACK_ID EPOCH_MJD RA_DEG DEC_DEG MAG OBSCODE OBJECT_NAME
# etc.
my %recoverable;     # available "recoverable" tracks, produced by guessTracklets
my %trktbl;     # all tracks created
my %mixed;
my %clean;

my %all_tracklets;      # save these by ID so we don't have to re-fetch from DB
my $line;

# Test for the recoverable file.  If it exists, load our recovery table.
unless ($recov_file) {   # already specified via --recov_file
    $recov_file = $tracks_file;
    $recov_file =~ s/\.sum$/.recoverable/;  # default recov filename
}

if (-r $recov_file) {   # appears to be present
    my $id;
    open my $fh, $recov_file or $mops_logger->logdie("can't read $recov_file");
    while (defined($line = <$fh>)) {
        ($id, undef) = split /\s+/, $line, 2;   # read id, one per line
        $recoverable{$id} = 1;                  # stuff in table
    }
    close $fh;
}


my ($orbit_id, $tracklet_id, $input_lineno);
my $last_orbit_id = '';


# Open LinkTracklets summary file and scan data.
my $stuffh = new FileHandle;
open $stuffh, $tracks_file or $mops_logger->logdie("can't open $tracks_file");

# Scan file and group lines by track ID.
my @t;
my %h;
my $i = 0;
while (defined($line = <$stuffh>)) {
    %h = miti_parse($line);
    push @{$trktbl{$h{ID}}}, [@h{qw(ID OBJECT_NAME EPOCH_MJD)}];  # add entire line to entry for this ID
    $i++;
    print STDERR "$i\n" if $i % 50000 == 0;
}
$mops_logger->info(sprintf("Found %d orbits.", scalar keys %trktbl));
close $stuffh;

# OK, now scan each detection's objectName.
foreach my $t (values %trktbl) {
    my %same;   # tally up different objects for orbit here
    my %mjds;   # count of different MJDs for these detections
    my $orbit_id;
    my $object_name;
    my $epoch_mjd;

    foreach my $det (@{$t}) {
        ($orbit_id, $object_name, $epoch_mjd) = @{$det};
        if ($object_name) {
            $same{$object_name}++;
        }
        $mjds{int($epoch_mjd)} = 1;
    }

    # For orbit to be counted as 'clean', require all same object and 3+ different MJDs.
    if (scalar keys %same == 1 and scalar keys %mjds > 2) {
        # All same
        $clean{$orbit_id} = $object_name;    # only key in hash
    }
    elsif (scalar keys %mjds > 2) {          # mixed w/sufficient obs
        $mixed{$orbit_id} = $orbit_id;
    }
}

my $tot_found = scalar keys %trktbl;
my $num_clean = scalar keys %clean;
my $num_mixed = scalar keys %mixed;
if ($tot_found > 0) {

    if ($summary) {
        printf "clean: %d (%.2f%%)\n", $num_clean, 100 * $num_clean / $tot_found;
        printf "mixed: %d (%.2f%%)\n", $num_mixed, 100 * $num_mixed / $tot_found;
    }

    elsif ($clean) {
        # Detail info for clean tracks
        foreach $orbit_id (keys %clean) {
            print $clean{$orbit_id}, "\t", $orbit_id, "\n";
        }
    }
    elsif ($mixed) {
        # Detail info for mixed tracks
        print $mixed{$_}, "\n" foreach keys %mixed;
    }
    elsif ($unfound) {
        # Walk the list of found.  If any of the objects/orbits was not
        # found in clean, print it.
        my %obj2clean = reverse %clean;
        foreach my $objectName (keys %recoverable) {
            print $objectName, "\n" unless exists($obj2clean{$objectName});
        }
    }
}
else {
    $mops_logger->warn("No tracks found.");
}

=head1 DESCRIPTION

Analyze the output of a LinkTracklets run.  Output:

=head1 SYNOPSIS

analyzeLinkTracklets [--clean] [--mixed] [--help] [--unfound] [--recov_file] [--help] tracks.miti

  tracks.miti : output file from LinkTracklets/lt2miti
  --summary : show summary statistics
  --clean : show objectNames of clean objects
  --mixed : show objectNames of mixed objects
  --unfound : show recoverable objects that were not found; requires track.recoverable file
  --recov_file : specify file containing recoverable objects
  --help : show man page

=item Number of recoverable orbits(1)

=item Number of recovered orbits

=item Number of mixed orbits

=cut
