#!/bin/env perl

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

use strict;

use Benchmark ':hireswallclock';

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

# Testing environment.
use Test::More tests=>18; # Perl testing framework.
use PS::MOPS::DC::Detection;
use PS::MOPS::Test::Instance;
use PS::MOPS::DC::Field;
use PS::MOPS::DC::DerivedObject;

# 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_d1; # test detection 1
our $g_d2; # test detection 1
our $g_s_d1; # serialized detection
our $g_ds_d1; # deserialized detection

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();

our $g_fld2=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 2...\n";
$g_fld2->insert();

our $g_do1=PS::MOPS::DC::DerivedObject->new($g_inst);

# Test definition 1.
# Create a new Detection.
# Expected result: Detection object.
#
# @return {1|0} Success is 1, failure is 0.
sub test_new
{
    my $success=0;
    $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,
                                       procId=>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,
                                       procId=>0,
                                      );

    if($g_d1=~/PS::MOPS::DC::Detection/ && $g_d2=~/PS::MOPS::DC::Detection/){
        $success=1;
    }
    return $success;
}

# Test definition 2.
# Add the Detection to a field.
# Expected result: Field ID for Detections is field ID of given Field.
#
# @return {1|0} Success is 1, failure is 0.
sub test_addToField
{
    my $success=-1;
    $g_d1->addToField($g_fld1); # detection is added to the db.
                                # fieldid is set for the detection.

    $g_d2->addToField($g_fld2); # detection is added to the db.

    # was going to use getField to verify test, but getField was not correct.
    if($g_d1->fieldId == 1 && $g_d2->fieldId == 2) { # check to see that fieldId was correctly assigned
        $success=1;
    }

    return $success;
}

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

# Test definition 4.
# Retrieve Detection given a Detection ID.
# Expected result: A Detection.
#
# @return {1|0} Success is 1, failure is 0.
sub test_modcd_retrieve__detId
{
    my $success=0;
    my $d=modcd_retrieve($g_inst,detId=>1);
    if($d=~/PS::MOPS::DC::Detection/){$success=1;}
    return $success;
}

# Test definition 5.
# Retrieve Detections from a set of Fields.
#
# skipping this for now - function is passing bind argument, sql has none
#
# Expected result: Detection(s).
#
# @return {1|0} Success is 1, failure is 0.
sub test_modcd_retrieve__fieldIds
{
    my $success=0;

    my @fields_array=(1,2);

    # pass the array reference of the fields array.
    my $d=modcd_retrieve($g_inst,fieldIds=>\@fields_array);
    if($d=~/PS::MOPS::DC::Detection/){$success=1;}
    return $success;
}

# Test definition 6.
# Retrieve Detections from a set of Fields.
#
# skipping this for now - function is passing bind argument, sql has none
#
# Expected result: Detection(s).
#
# @return {1|0} Success is 1, failure is 0.
sub test_modcd_retrieve__fieldIds__trackletOnly
{
    my $success=0;

    my @fields_array=(1);

    my $d=modcd_retrieve($g_inst,
                         fieldIds=>\@fields_array,
                         trackletOnly=>1);
    if($d=~/PS::MOPS::DC::Detection/){$success=1;}
    return $success;
}

# Test definition 7.
# Retrieve Detections from a set of Fields.
# Expected result: Detection(s).
#
# @return {1|0} Success is 1, failure is 0.
sub test_modcd_retrieve__fieldIds__not_trackletOnly
{
    my $success=0;

    my @fields_array=(1);

    my $d=modcd_retrieve($g_inst,
                         fieldIds=>\@fields_array,
                         trackletOnly=>0);
    if($d=~/PS::MOPS::DC::Detection/){$success=1;}
    return $success;
}

# Test definition 8.
# Retrieve Detections from a set of Fields.
# Expected result: detection matching "test object 1"
#
# @return {1|0} Success is 1, failure is 0.
sub test_modcd_retrieve__objectName
{
    my $success=0;

    my $d_iter=modcd_retrieve($g_inst,
                              objectName=>"test object 1",
                             );

    my $d=$d_iter->next();

    if($d=~/PS::MOPS::DC::Detection/){$success=1;}

    $d=$d_iter->next();

    # if more than one than fail
    if($d=~/PS::MOPS::DC::Detection/){$success=0;}

    return $success;
}

# Test definition 9.
# Retrieve Detections from a set of Fields.
#
# the detection is associated with a DO
#
# Expected result: Detection(s).
#
# @return {1|0} Success is 1, failure is 0.
sub test_modcd_retrieve__derivedobject
{
    my $success=0;

    my $d_iter=modcd_retrieve($g_inst,
                              objectName=>"test object 1",
                             );
    my $d=$d_iter->next();

    if($d=~/PS::MOPS::DC::Detection/){$success=1;}

    $d=$d_iter->next();

    # if more than one than fail
    if($d=~/PS::MOPS::DC::Detection/){$success=0;}

    return $success;
}

# Test definition 10.
# Retrieve Detections from a set of Fields.
# Expected result: Detection(s).
#
# @return {1|0} Success is 1, failure is 0.
sub test_modcd_retrieve__mjd
{
    my $success=0;

    my $d_iter=modcd_retrieve($g_inst,
                              mjd=>56000,
                             );
    my $d=$d_iter->next();

    if($d=~/PS::MOPS::DC::Detection/){$success=1;}

=skip
    # the implementation using
    #    $selectall_sql
    #    from detections d
    #    where status='$status' $s2n_selector
    #    and d.field_id in (
    #    select field_id from `fields`
    #    where epoch_mjd >= ? and epoch_mjd < ?)
    # is not going to retrieve anything due to where epoch_mjd >= ? and epoch_mjd < ?.

    $d=$d_iter->next();

    # if more than one than fail
    if($d=~/PS::MOPS::DC::Detection/){$success=0;}
=cut

    return $success;
}

# Test definition 11.
# Delete a Detection.
# Expected result: DB record is deleted.
#
# @return {1|0} Success is 1, failure is 0.
sub modcd_delete__single
{
    my $success=0;
    modcd_delete($g_inst,detId=>1);
    my $d=modcd_retrieve($g_inst,detId=>1);
    if(!$d){$success=1;}
    return $success;
}

# Test definition 12.
# Delete a Detection.
# Expected result: DB records are deleted.
#
# @return {1|0} Success is 1, failure is 0.
sub modcd_delete__multiple
{
    my $success=0;
    $g_d1->addToField($g_fld1);
    print STDERR "g_d1 id=$g_d1->{detId}\n";
    print STDERR "g_d2 id=$g_d2->{detId}\n";
    modcd_delete($g_inst,detId=>3);
    modcd_delete($g_inst,detId=>2);
    my $d1=modcd_retrieve($g_inst,detId=>3);
    my $d2=modcd_retrieve($g_inst,detId=>2);
    if(!$d1 && !$d2){$success=1;}
    return $success;
}

# Test definition 13.
# Classify a set of clean detections.
# Expected result: Classification is clean.
#
# @return {1|0} Success is 1, failure is 0.
sub modcd_classifyDetections__clean
{
    my $success=0;
    $g_d1->{objectName}="S001";
    $g_d2->{objectName}="S001";
    my @dets=($g_d1,$g_d2);
    my $result=modcd_classifyDetections($g_inst,@dets);
    if($result eq "C"){$success=1;}
    return $success;
}

# Test definition 14.
# Classify a set of mixed detections.
# Expected result: Classification is mixed.
#
# @return {1|0} Success is 1, failure is 0.
sub modcd_classifyDetections__mixed
{
    my $success=0;
    $g_d1->{objectName}="S001";
    $g_d2->{objectName}="S002";
    my @dets=($g_d1,$g_d2);
    my $result=modcd_classifyDetections($g_inst,@dets);
    if($result eq "M"){$success=1;}
    return $success;
}

# Test definition 15.
# Classify a set of bad detections.
# Expected result: Classification is bad.
#
# @return {1|0} Success is 1, failure is 0.
sub modcd_classifyDetections__bad
{
    my $success=0;
    $g_d1->{objectName}="S001";
    $g_d2->{objectName}="";
    my @dets=($g_d1,$g_d2);
    my $result=modcd_classifyDetections($g_inst,@dets);
    if($result eq "B"){$success=1;}
    return $success;
}

# Test definition 16.
# Classify a set of nonsynthetic detections.
# Expected result: Classification is nonsynthetic.
#
# @return {1|0} Success is 1, failure is 0.
sub modcd_classifyDetections__nonsynthetic
{
    my $success=0;
    $g_d1->{objectName}="001";
    $g_d2->{objectName}="002";
    my @dets=($g_d1,$g_d2);
    my $result=modcd_classifyDetections($g_inst,@dets);
    if($result eq "N"){$success=1;}
    return $success;
}

# Test definition 17.
# Serialize a detection.
# Expected result: Serialized detection.
#
# @return {1|0} Success is 1, failure is 0.
sub test_serialize
{
    my $success=0;
    $g_s_d1=$g_d1->serialize();
    print $g_s_d1;
    print "\n";

    if($g_s_d1 eq "MIF-D 1 1 0 0 56000 0 undef w 0 undef undef undef undef undef 001 0 0 undef F 5100 0"){
        $success=1;
    }
    return $success;
}

# Test definition 18.
# Deserialize a serialized detection.
# Expected result: A detection.
#
# @return {1|0} Success is 1, failure is 0.
sub test_modcd_deserialize
{
    my $success=0;
    $g_ds_d1=modcd_deserialize($g_inst,$g_s_d1);
    # compare content of g_s_d1 and g_d1
    if($g_ds_d1->{epoch} eq "56000" &&
       $g_ds_d1->{fieldId} eq "1" &&
       $g_ds_d1->{dec} eq "0" &&
       $g_ds_d1->{filter} eq "w" &&
       $g_ds_d1->{objectName} eq "001"){$success=1;}
    return $success;}

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

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

# Perform test test_getField.
$g_start=new Benchmark;
TODO: {
    # @todo output a line for test-runner to flag test as ni

    local $TODO="function is not correctly written";
    ok(test_getField, "PS-MOPS-DC-Detection->test_getField");
}
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Detection->test_getField: " . timestr(timediff($g_end,$g_start),'all') . "\n";

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

# Perform test test_modcd_retrieve__fieldIds.
$g_start=new Benchmark;
TODO: {
    local $TODO="one bind argument is passed when sql statement has none";

# todo_skip doesn't output the name of the test!!!
# need to output the test name and parse the test name separately for todo_skip cases.

    todo_skip "one bind argument is passed when sql statement has none",1;
    ok(test_modcd_retrieve__fieldIds, "PS-MOPS-DC-Detection->test_modcd_retrieve__fieldIds");
}
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Detection->test_modcd_retrieve__fieldIds: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test test_modcd_retrieve__fieldIds__trackletOnly.
$g_start=new Benchmark;

TODO: {
    todo_skip "one bind argument is passed when sql statement has none",1;
    ok(test_modcd_retrieve__fieldIds__trackletOnly, "PS-MOPS-DC-Detection->test_modcd_retrieve__fieldIds__trackletOnly");
}

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

# Perform test test_modcd_retrieve__fieldIds__not_trackletOnly.
$g_start=new Benchmark;

TODO: {
    todo_skip "one bind argument is passed when sql statement has none",1;
    ok(test_modcd_retrieve__fieldIds__not_trackletOnly, "PS-MOPS-DC-Detection->test_modcd_retrieve__fieldIds__not_trackletOnly");
}

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

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

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

# Perform test test_modcd_retrieve__mjd.
$g_start=new Benchmark;

TODO: {
    todo_skip "sql is searching for >= arg *AND* < arg",1;
    ok(test_modcd_retrieve__mjd, "PS-MOPS-DC-Detection->test_modcd_retrieve__mjd");
}
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Detection->test_modcd_retrieve__mjd: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Perform test modcd_classifyDetections__clean.
$g_start=new Benchmark;
TODO: {
    local $TODO="investigate clean classification";
    ok(modcd_classifyDetections__clean, "PS-MOPS-DC-Detection->modcd_classifyDetections__clean");
}
$g_end=new Benchmark;
print "time: PS-MOPS-DC-Detection->modcd_classifyDetections__clean: " . timestr(timediff($g_end,$g_start),'all') . "\n";

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

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

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

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

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

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

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