#!/bin/env perl

# This is a standalone testing executable for PS::MOPS::ExportLib.
# Testing ExportLib requires the use of a preexisting DB.
# The DB or Instance is passed through subroutine arguments.

use strict;

use Benchmark ':hireswallclock';

# Define variables for benchmarking.
our $g_start;
our $g_end;
our $g_diff;

# Testing environment.
use Test::More tests=>9; # Perl testing framework.
use PS::MOPS::ExportLib;
use PS::MOPS::DC::Instance;
use PS::MOPS::DC::Orbit;
use PS::MOPS::Test::Instance;
use PS::MOPS::DC::DerivedObject;
use PS::MOPS::DC::Detection;
use PS::MOPS::DC::Tracklet;

my $fh_test=*TEST_FILEHANDLE;
my $test_inst=PS::MOPS::Test::Instance->new();
my $inst=$test_inst->getPSMOPSInstance();

my @de=(0,0,0,0,0,0,0,0,0,0);
my $fld=PS::MOPS::DC::Field->new($inst,
                                 epoch=>0,
                                 filter=>'w', # referential integrity enforced.
                                 timeStop=>0,
                                 dec=>0,
                                 raSigma=>0,
                                 surveyMode=>0,
                                 de=>\@de,
                                 decSigma=>0,
                                 ra=>0,
                                 timeStart=>0,
                                 obscode=>0,
                                 limitingMag=>0
);
$fld->insert();

# Create test detections


my @detections=();
for(my $i=0; $i<8; $i++){
    $detections[$i]=PS::MOPS::DC::Detection->new($inst,
                                         mag=>21.91,
                                         dec=>-3.87,
                                         ra=>340.63,
                                         epoch=>54079.24,
                                         isSynthetic=>1,
                                         filter=>'r',
                                         s2n=>10.69,
                                         raSigma=>0.01,
                                         decSigma=>0.01,
                                         magSigma=>0.01,
                                         objectName=>'test_object');
}    
#$det->addToField($fld);

my @test_dets;

# Insert multiple detections
for(my $i=0; $i<8; $i++){
    $detections[$i]->{epoch}=$detections[$i]->{epoch} + $i;
    $detections[$i]->addToField($fld);
}

# Associate detections with tracklets

# Each tracklet should have one detection.

my @tracklets;

for(my $i=0; $i<8; $i++){
    my @tmp_dets=();
    push(@tmp_dets,$detections[$i]); # Create an array of detections.
    $tracklets[$i]=PS::MOPS::DC::Tracklet->new($inst,
                                               classification=>'C',
                                               detections=>\@tmp_dets);
    $tracklets[$i]->insert();
}

my $do_name="L00000";

my $orb=PS::MOPS::DC::Orbit->new($inst,
                                 argPeri=>9.34,
                                 node=>13.67,
                                 i=>3.91,
                                 e=>0.24,
                                 timePeri=>54136.0,
                                 q=>1.93,
                                 hV=>17.39,
                                 epoch=>54083,
                                 residual=>0.01,
                                 arcLength_days=>31
                                 );

my $orbit_id=$orb->insert();

my $do=PS::MOPS::DC::DerivedObject->new($inst,
                                        mopsClassification=>"MB",
                                        orbitId=>$orbit_id);
$do->insert();
my $do_id=$do->{derivedobjectId};

# Attribute the tracklets to the DO.
$do->attributeTracklets(TRACKLETS_AREF=>\@tracklets);

sub test_write_des_orbit_line
{    
    open($fh_test, ">export_test_file.txt");
    my $is_synthetic=1;
    write_des_orbit_line($fh_test,$do_id,$orb,$is_synthetic);
    close($fh_test);
    
    open($fh_test, "<export_test_file.txt");
    my @data=<$fh_test>;
    close($fh_test);
    if($data[0]=~s/\n//){} # remove linefeeds
    if($data[0] eq "1 COM 1.93 0.24 3.91 13.67 9.34 54136 17.39 54083 1 6 -1 MOPS"){
        return 1;
    }
    
    return 0;
}

sub test_write_des_tracklet_line
{
    # What args does the tracklet routine take?   
    
    # Create a test filehandle.
    open($fh_test, ">des_tracklet_test.txt");
    write_des_tracklet_line($inst, $fh_test, $do_name, $detections[0]);
    close($fh_test);
    
    # Read the written file.
    open(FILE,"<des_tracklet_test.txt");
    my @data=<FILE>;
    close(FILE);
    
    if($data[0]=~s/\n//g){}
    
    if($data[0] eq "L00000 1"){
        return 1;
    }
    return 0;
}

sub test_write_des_detection_line
{
    my $removal=0;
    my $synthetic=1;
    my $do_id=1;
    # Create a test filehandle.
    open($fh_test, ">des_detection_test.txt");
    write_des_detection_line($fh_test, $do_id, $detections[0], $removal, $synthetic);
    close($fh_test);
    
    # Read the written file.
    open(FILE,"<des_detection_test.txt");
    my @data=<FILE>;
    close(FILE);
    
    if($data[0]=~s/\n//g){}
    
    if($data[0] eq "S1 54079.24 O 340.63 -3.87 21.91 r 0 36 36 0.01 10.69 test_object"){
        return 1;
    }
    return 0;
}

sub test_is_exportable
{
    if(is_exportable($inst, $do_id)){
        return 1;
    }
    return 0;
}

sub test_update_datastore_index
{
    my $det_name="test_detections";
    my $tlet_name="test_tracklets";
    my $orb_name="test_orbits";
    my $path_override=".";
    update_datastore_index($det_name,$tlet_name,$orb_name,$path_override);
    if(-e "./index"){
        return 1;
    }
    return 0;
}

sub test_retrieve_orbit
{
    # Retrieve the test orbit associated with the test DO.
    my $orb=retrieve_orbit($inst,$do_id);
    
    # Check three points of data.
    if($orb->{i} eq "3.91" &&
       $orb->{e} eq "0.24" &&
       $orb->{residual} eq "0.01") {
        return 1;
    }
    return 0;
}

sub test_get_number_of_exports
{
    my $number_of_exports=get_number_of_exports($inst,$do_id);
    if($number_of_exports==0){
        return 1;
    }
    return 0;
}

sub test_send_email_notification
{
    # Test email message generation.
    my @test_files=qw(file_link1 file_link2 file_link3);
    my $email=send_email_notification($inst,\@test_files,1);
    if($email=~/file_link1/){
        if($email=~/file_link2/){
            if($email=~/file_link3/){
                return 1;
            }
        }
    }
    return 0;
}

sub test_export_pending_mops_objects
{
    my $testing_mode=1;
    my $result=export_pending_mops_objects($inst,$testing_mode);
    if(!$result){ # No records marked for export.
                  # No revision records created.
        return 1;
    }
    return 0;
}

# Test: test_something
ok(test_write_des_orbit_line, "PS::MOPS::ExportLib->test_write_des_orbit_line");
ok(test_write_des_tracklet_line, "PS::MOPS::ExportLib->test_write_des_tracklet_line");
ok(test_write_des_detection_line, "PS::MOPS::ExportLib->test_write_des_detection_line");
ok(test_is_exportable, "PS::MOPS::ExportLib->test_is_exportable");
ok(test_update_datastore_index, "PS::MOPS::ExportLib->test_update_datastore_index");
ok(test_retrieve_orbit, "PS::MOPS::ExportLib->test_retrieve_orbit");
ok(test_get_number_of_exports, "PS::MOPS::ExportLib->test_get_number_of_exports");
ok(test_send_email_notification, "PS::MOPS::ExportLib->test_send_email_notification");
ok(test_export_pending_mops_objects, "PS::MOPS::ExportLib->test_export_pending_mops_objects");
