#!/bin/env perl

# This is a standalone testing executable for PS::MOPS::DC::Tracklet.

use strict;

use Benchmark ':hireswallclock';

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

# Testing environment.
use Test::More tests=>14; # Perl testing framework.
use PS::MOPS::DC::Tracklet;
use PS::MOPS::Test::Instance;
use PS::MOPS::DC::Detection;
use PS::MOPS::DC::DerivedObject;
use PS::MOPS::Constants qw(:all);

# Make the PS-MOPS Instance available through $g_inst and
# the Test Instance available through $g_test_inst.
our $g_test_inst=PS::MOPS::Test::Instance->new();
our $g_inst=$g_test_inst->getPSMOPSInstance();

our $g_t1; # tracklet

our $g_d1; # detection
our $g_d2; # detection

$g_d1=PS::MOPS::DC::Detection->new($g_inst,
                                   objectName=>"test object 1",
                                   mag=>0,
                                   dec=>0,
                                   ra=>0,
                                   epoch=>'56000',
                                   isSynthetic=>0,
                                   filter=>'w', # value enforced by ref integrity
                                   s2n=>0,
                                  );

$g_d2=PS::MOPS::DC::Detection->new($g_inst,
                                   objectName=>"test object 2",
                                   mag=>0,
                                   dec=>0,
                                   ra=>0,
                                   epoch=>'56001',
                                   isSynthetic=>0,
                                   filter=>'w', # value enforced by ref integrity
                                   s2n=>0,
                                  );

my @de=(0,0,0,0,0,0,0,0,0,0);
our $g_fld1=PS::MOPS::DC::Field->new($g_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
                                   );
print STDERR "Inserting test field 1...\n";
$g_fld1->insert();

# insert detections to db while associating with field
$g_d1->addToField($g_fld1); # detection is added to the db.
$g_d2->addToField($g_fld1); # detection is added to the db.

# make derived objects
our $g_do1=PS::MOPS::DC::DerivedObject->new($g_inst); # Passing g_inst here is critical.

# insert derived objects
$g_do1->insert();

our @g_dets_array=($g_d1,$g_d2);

$g_t1=PS::MOPS::DC::Tracklet->new($g_inst,
                                  detections=>\@g_dets_array,
                                  fieldId=>1,
                                  classification=>$MOPS_EFF_CLEAN);
$g_t1->insert();

my @g_t_array=($g_t1);
$g_do1->attributeTracklets(TRACKLETS_AREF=>\@g_t_array);

# Start test definitions
# ===========================================================================

# Test definition 1.
# Create a new tracklet.
# Expected result: Tracklet
#
# @return {1|0} Success is 1, failure is 0.
sub test_new
{
    my $success=0;

    # @note tracklet creation doesnt require a detections array but uses it during
    # object creation

    my @dets=($g_d1,$g_d2);

    $g_t1=PS::MOPS::DC::Tracklet->new($g_inst,
                                      detections=>\@dets,
                                      fieldId=>1,
                                      classification=>$MOPS_EFF_CLEAN);
    if($g_t1=~/PS::MOPS::DC::Tracklet/){$success=1;}
    return $success;
}

# Test definition 2.
# insert a tracklet into the db
# Expected result: new db row
#
# @return {1|0} Success is 1, failure is 0.
sub test_insert
{
    my $success=0;

    $g_t1->insert();
    my $t=modct_retrieve($g_inst,trackletId=>2);
    if($t=~/PS::MOPS::DC::Tracklet/ && $t->{trackletId} eq "2"){$success=1;}

    return $success;
}

# Test definition 3.
# not implemented
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_delete
{
    my $success=0;
    return $success;
}

# Test definition 4.
# set status for tracklet
# Expected result: status is set
#
# @return {1|0} Success is 1, failure is 0.
sub test_status__set
{
    my $success=0;
    $g_t1->status('U'); # set status to U unattributed
    if($g_t1->{status} eq "U"){$success=1;}
    return $success;
}

# Test definition 5.
# get status for tracklet
# Expected result: status
#
# @return {1|0} Success is 1, failure is 0.
sub test_status__get
{
    my $success=0;
    if($g_t1->{status} eq "U"){$success=1;}
    return $success;
}

# Test definition 6.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_retrieve__trackletId
{
    my $success=0;
    my $result=modct_retrieve($g_inst,trackletId=>2);
    if($result=~/PS::MOPS::DC::Tracklet/){$success=1;}
    return $success;
}

# Test definition 7.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_retrieve__fieldId
{
    my $success=0;
    my $result=modct_retrieve($g_inst,fieldId=>1); # in iterator is returned
    my $t=$result->next();
    if($t=~/PS::MOPS::DC::Tracklet/){$success=1;}
    $t=$result->next();
    $t=$result->next();
    if($t){$success=0;}
    return $success;
}

# Test definition 8.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_retrieve__detectionId
{
    my $success=0;
    my $result=modct_retrieve($g_inst,detectionId=>1); # in iterator is returned
    my $t=$result->next();
    if($t=~/PS::MOPS::DC::Tracklet/){$success=1;}
    $t=$result->next();
    $t=$result->next();
    if($t){$success=0;}
    return $success;
}

# Test definition 9.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_retrieve__derivedobjectId
{
    my $success=0;

    # select tracklets attributed to a DO

    my $result=modct_retrieve($g_inst,derivedobjectId=>1); # in iterator is returned
    my $t=$result->next();
    if($t=~/PS::MOPS::DC::Tracklet/){$success=1;}
    $t=$result->next();
    if($t){$success=0;}
    return $success;
}

# Test definition 10.
# not implemented
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_delete
{
    my $success=0;
    return $success;
}

# Test definition 11.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_selectTracklets__mjd
{
    my $success=0;

    my $result=modct_selectTracklets($g_inst,
                                     mjd=>56000);
    my $t=$result->next();
    if($t=~/PS::MOPS::DC::Tracklet/){$success=1;}

    return $success;
}

# Test definition 12.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_selectTracklets__mjd1
{
    my $success=0;
    my $result=modct_selectTracklets($g_inst,
                                     mjd1=>56000);
    my $t=$result->next();
    if($t=~/PS::MOPS::DC::Tracklet/){$success=1;}

    return $success;
}

# Test definition 14.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_selectTrackletIdsByFieldId
{
    my $success=0;
    my $result=modct_selectTrackletIdsByFieldId($g_inst,fieldId=>1);
    foreach my $t_id (@{$result}){
        $success=1;
        if($t_id ne "2"){
            $success=0;
        }
    }
    return $success;
}

# Test definition 15.
# variations
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_modct_selectDetracklets
{
    my $success=0;
    my @dets;
    my $result=modct_selectDetracklets($g_inst,trackletId=>2);
    my $d=$result->next();
    if($d=~/PS::MOPS::DC::Detection/){push(@dets,$d);}
    $d=$result->next();
    if($d=~/PS::MOPS::DC::Detection/){push(@dets,$d);}

    # count the number of dets, should be 2
    if(($#dets+1)==2){$success=1;}

    return $success;
}

# Test definition 16.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
#
# @todo use multiple fields and field epochs for this test
sub test_modct_getLastFieldId
{
    my $success=0;
    my @tlets=($g_t1);
    my $result=modct_getLastFieldId($g_inst,@tlets);
    if($result eq "1"){$success=1;}
    return $success;
}

# Perform test test_new.
$g_start=new Benchmark;
ok(test_new, "PS-MOPS-DC-Tracklet->test_new");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_new: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_insert.
$g_start=new Benchmark;
ok(test_insert, "PS-MOPS-DC-Tracklet->test_insert");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_insert: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_status__set.
$g_start=new Benchmark;
ok(test_status__set, "PS-MOPS-DC-Tracklet->test_status__set");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_status__set: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_status__get.
$g_start=new Benchmark;
ok(test_status__get, "PS-MOPS-DC-Tracklet->test_status__get");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_status__get: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_retrieve__trackletId.
$g_start=new Benchmark;
ok(test_modct_retrieve__trackletId, "PS-MOPS-DC-Tracklet->test_modct_retrieve__trackletId");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_retrieve__trackletId: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_retrieve__fieldId.
$g_start=new Benchmark;
ok(test_modct_retrieve__fieldId, "PS-MOPS-DC-Tracklet->test_modct_retrieve__fieldId");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_retrieve__fieldId: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_retrieve__detectionId.
$g_start=new Benchmark;
ok(test_modct_retrieve__detectionId, "PS-MOPS-DC-Tracklet->test_modct_retrieve__detectionId");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_retrieve__detectionId: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_retrieve__derivedobjectId.
$g_start=new Benchmark;
ok(test_modct_retrieve__derivedobjectId, "PS-MOPS-DC-Tracklet->test_modct_retrieve__derivedobjectId");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_retrieve__derivedobjectId: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_delete.
$g_start=new Benchmark;

TODO: {
    local $TODO="code not implemented";
    ok(test_modct_delete, "PS-MOPS-DC-Tracklet->test_modct_delete");
}

$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_delete: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_selectTracklets__mjd.
$g_start=new Benchmark;

TODO: {
    todo_skip "PS-MOPS-DC-Tracklet->test_modct_selectTracklets__mjd: command out of sync error reported",1;
    ok(test_modct_selectTracklets__mjd, "PS-MOPS-DC-Tracklet->test_modct_selectTracklets__mjd");
}

$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_selectTracklets__mjd: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_selectTracklets__mjd1.
$g_start=new Benchmark;

TODO: {
    todo_skip "PS-MOPS-DC-Tracklet->test_modct_selectTracklets__mjd1: command out of sync error reported",1;
    ok(test_modct_selectTracklets__mjd1, "PS-MOPS-DC-Tracklet->test_modct_selectTracklets__mjd1");
}

$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_selectTracklets__mjd1: " . timestr(timediff($g_end,$g_start),'all') . "\n";

## Perform test test_modct_selectTracklets__mjd.
#$g_start=new Benchmark;
#ok(test_modct_selectTracklets__mjd, "PS-MOPS-DC-Tracklet->test_modct_selectTracklets__mjd");
#$g_end=new Benchmark;
#print "time: PS-MOPS-DC-Tracklet->test_modct_selectTracklets__mjd: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_selectTrackletIdsByFieldId.
$g_start=new Benchmark;
ok(test_modct_selectTrackletIdsByFieldId, "PS-MOPS-DC-Tracklet->test_modct_selectTrackletIdsByFieldId");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_selectTrackletIdsByFieldId: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_selectDetracklets.
$g_start=new Benchmark;
ok(test_modct_selectDetracklets, "PS-MOPS-DC-Tracklet->test_modct_selectDetracklets");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_selectDetracklets: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modct_getLastFieldId.
$g_start=new Benchmark;
ok(test_modct_getLastFieldId, "PS-MOPS-DC-Tracklet->test_modct_getLastFieldId");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_modct_getLastFieldId: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# perform last

=skip

# Perform test test_delete.
$g_start=new Benchmark;
ok(test_delete, "PS-MOPS-DC-Tracklet->test_delete");
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Tracklet->test_delete: " . timestr(timediff($g_end,$g_start),'all') . "\n";

=cut
