#!/bin/env perl

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

use strict;

use Benchmark ':hireswallclock';

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

# Testing environment.
use Test::More tests=>21; # Perl testing framework.
use PS::MOPS::Lib;

# Test definition 1.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_getOCNum
{
    my $success=0;
    my $mjd=54000;
    my $ocnum=mopslib_getOCNum($mjd);
    if($ocnum==82){$success=1;}
    return $success;
}

# Test definition 2.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_photoS2N
{
    my $success=0;
    my $apparent_magnitude=21;
    my $exposure_time=30;
    my $photometric_signal_to_noise=mopslib_photoS2N($apparent_magnitude,$exposure_time);
    print "$photometric_signal_to_noise\n";
    if($photometric_signal_to_noise<=(71.27516 + .00001) && $photometric_signal_to_noise>=(71.27516 - .00001)){$success=1;}
    return $success;
}

# Test definition 3.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_photoS2Nx
{
    my $success=0;
    my $mag=16;
    my $filter='r';
    
    use PS::MOPS::Test::Instance;
    
    my $t_inst=PS::MOPS::Test::Instance->new();
    my $inst=$t_inst->getPSMOPSInstance();

    my $mops_config = $inst->getConfig;
    
    my $s2n_config = $mops_config->{site}->{s2n_config};
    
    my $r=mopslib_photoS2Nx($mag,$filter,$s2n_config);
    if(between($r,3674.84845,3674.84847)){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 4.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_astroError
{
    my $success=0;
    my $apparent_magnitude=21;
    my $astrometric_error=mopslib_astroError($apparent_magnitude);
    if($astrometric_error<=(0.00491 + .00001)&&$astrometric_error>=(0.00491 - .00001)){
        $success=1;
    }
    return $success;
}

# Test definition 5.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_photoError
{
    my $success=0;
    my $apparent_magnitude=21;
    my $photometric_error=mopslib_photoError($apparent_magnitude);
    if($photometric_error<=(0.01534 + 0.00001) && $photometric_error>=(0.01534 - 0.00001)){$success=1;}
    return $success;
}

# Test definition 6.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_fuzzRDM
{
    my $success=0;
    my $RA=10.955;
    my $DEC=10.631;
    my $apparent_magnitude=21;
    my @val=mopslib_fuzzRDM($RA,$DEC,$apparent_magnitude);
    if( ($val[0]<= (10.95499 + 0.001) && $val[0] >= (10.95499 - 0.001) ) &&
        ($val[1]<= (10.63100 + 0.00001) && $val[1] >= (10.63100 - 0.00001) ) &&
        ($val[2]<= (20.98966 + 1) && $val[2] >= (20.98966 - 1) ) ) {$success=1;}
    return $success;
}

# Test definition 7.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_fuzzRDM2
{
    my $success=0;
    my $RA=10.955;
    my $DEC=10.631;
    my $apparent_magnitude=21;
    my $val=mopslib_fuzzRDM2($RA,$DEC,$apparent_magnitude);
    if(within_error($val->{DEC_DEG},10.631,0.01) &&
       within_error($val->{DEG_SIGMA_DEG},1.349e-06,0.001) &&
       within_error($val->{MAG},20.988,1) &&
       within_error($val->{RA_DEG},10.955,0.01) &&
       within_error($val->{RA_SIGMA_DEG},1.349e-06,0.001) &&
       within_error($val->{S2N},72.065,5) ) {$success=1;}
    return $success;
}

sub within_error
{
    my($actual,$target,$error)=@_;
    my $success=0;
    if($actual <= ($target + $error) && $actual >= ($target - $error) ) {$success=1;}
    return $success;
}

# Test definition 8.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_fuzzRDM3
{
    my $success=0;
    my $ra=10.955;
    my $dec=10.631;
    my $mag=21;
    my $bias=0.1;
    my $filter='r';
    
    use PS::MOPS::Test::Instance;
    
    my $t_inst=PS::MOPS::Test::Instance->new();
    my $inst=$t_inst->getPSMOPSInstance();

    my $mops_config = $inst->getConfig;
    
    my $s2n_config = $mops_config->{site}->{s2n_config};
    
    my $r=mopslib_fuzzRDM3($ra,$dec,$mag,$bias,$filter,$s2n_config);
    
    # @todo add more test values    
    if(between($r->{DEC_DEG},10.63101,10.63099) &&
       between($r->{MAG},20.98390,20.98388)){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 9.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_mutateControlObject
{
    my $success=0;
    use PS::MOPS::Test::Instance;
    use PS::MOPS::DC::Detection;
    
    my $t_inst=PS::MOPS::Test::Instance->new();
    my $inst=$t_inst->getPSMOPSInstance();
    my $det=PS::MOPS::DC::Detection->new($inst,
                                         objectName=>'SM00000',
                                         mag=>0,
                                         dec=>0,
                                         ra=>0,
                                         epoch=>54000,
                                         isSynthetic=>1,
                                         filter=>'r',
                                         s2n=>1,
                                         orient_deg=>0);
    my $time=0;
    
    my $r=mopslib_mutateControlObject($det,$time);
    print "info: : det->orient_deg=$det->{orient_deg}\n";
    if($det->{orient_deg}==180||$det->{orient_deg}==0){$success=1;}
    else {$success=0;}
    return $success;
}

# Test definition 10.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_mjd2nn
{
    my $success=0;
    my $mjd=54000;
    my $offset=-10;
    my $r=mopslib_mjd2nn($mjd,$offset);
    if($r==53999){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 11.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_nn2mjd
{
    my $success=0;
    my $nn=53999;
    my $offset=-10;
    my $r=mopslib_nn2mjd($nn,$offset);
    if(between($r,53999.91667,53999.91665)){$success=1;}
    else{$success=0;}
    return $success;
}

sub between {
    my($v,$x1,$x2)=@_;
    my $diff=abs($x1-$x2);
    my $half=$diff/2;
    
    if($v<($v+$half) && $v>($v-$half)){
        return 1;
    }
    return 0;
}

# Test definition 12.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_mjd2localtimestr
{
    my $success=0;
    my $mjd=54000;
    my $offset=-10;
    my $r=mopslib_mjd2localtimestr($mjd,$offset);
    if($r eq "2006-09-21-14:00:00.0"){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 13.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_calculateDCriterion
{
    my $success=0;
    use PS::MOPS::Test::Instance;
    use PS::MOPS::DC::Orbit;
    my $t_inst=PS::MOPS::Test::Instance->new();
    my $inst=$t_inst->getPSMOPSInstance();
    
    my $o1=PS::MOPS::DC::Orbit->new($inst,
                                    argPeri=>0,
                                    node=>0,
                                    i=>0,
                                    e=>0,
                                    epoch=>54000,
                                    timePeri=>0,
                                    q=>0,
                                    hV=>20);
    my $o2=PS::MOPS::DC::Orbit->new($inst,
                                    argPeri=>0,
                                    node=>0,
                                    i=>0,
                                    e=>0.1,
                                    epoch=>54000,
                                    timePeri=>0,
                                    q=>0,
                                    hV=>20);
    my $r=mopslib_calculateDCriterion($o1,$o2);
    if($r==0.1){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 14.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_V2filt
{
    my $success=0;
    my $mag=20;
    my $filter="r";
    my $r=mopslib_V2filt($mag,$filter);
    if($r==19.77){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 15.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_filt2V
{
    my $success=0;
    my $mag=20;
    my $filter="r"; 
    my $r=mopslib_filt2V($mag,$filter);
    if($r==20.23){$success=1}
    else{$success=0;}
    return $success;
}

# Test definition 16.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_effClassifyObjectNames
{
    my $success=0;
    my @names=qw(MB0000001 MB0000002 MB0000003);
    my $r=mopslib_effClassifyObjectNames(@names);
    if($r eq "N"){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 17.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_classifyObject
{
    my $success=0;
    use PS::MOPS::Test::Instance;
    use PS::MOPS::DC::Orbit;
    my $t_inst=PS::MOPS::Test::Instance->new();
    my $inst=$t_inst->getPSMOPSInstance();
    
    my $o1=PS::MOPS::DC::Orbit->new($inst,
                                    argPeri=>0,
                                    node=>0,
                                    i=>0,
                                    e=>0,
                                    epoch=>54000,
                                    timePeri=>0,
                                    q=>0,
                                    hV=>20);
    my $r=mopslib_classifyObject($o1);
    if($r eq "UNK"){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 18.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_hsn2flux
{
    my $success=0;
    my $mag=20;
    my $s2n=1;
    my $filter='r';
    my $r=mopslib_hsn2flux($mag,$s2n,$filter);
    if(between($r,109.64780,109.64782)){$success=1;}
    else{$success=0;}
    return $success;
}

# Test definition 19.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_flux2hsn
{
    my $success=0;
    my $flux=109.64781;
    my $flux_sigma=0.1;
    my $filter='r';
    my $r=mopslib_flux2hsn($flux,$flux_sigma,$filter);
    if(between($r,1096.4782,1096.4780)){$success=1;}
    else{$success=0;}   
    return $success;
}

# Test definition 20.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_mag2fluxsn
{
    my $success=0;
    my $mag=20;
    my $mag_sigma=0.1;
    my $filter='r';
    my $r=mopslib_mag2fluxsn($mag,$mag_sigma,$filter);
    if(between($r,10.85735,10.85737)){$success=1;}
    else{$success=0;}      
    return $success;
}

# Test definition 21.
#
# Expected result:
#
# @return {1|0} Success is 1, failure is 0.
sub test_mopslib_parseOrbfitOptsFile
{
    my $success=0;
    my $file="orbfit.opt";
    my $section="ATTRIB";
    my $argsref="";
    my $r=mopslib_parseOrbfitOptsFile($file,$section,$argsref);
    my $r2;
    
#    open(FILE,">orbfit-opts-attrib.txt");
#    print FILE $r;
#    close(FILE);
    
    open(FILE,"<orbfit-opts-attrib.txt");
    my @data=<FILE>;
    close(FILE);
    
    foreach my $line (@data) { $r2.=$line; }

    if($r eq $r2) {$success=1;}
    else {$success=0;}
    return $success;
}

# Test 1: test_mopslib_getOCNum.
$g_start=new Benchmark;
ok(test_mopslib_getOCNum, "PS-MOPS-Lib_2->test_mopslib_getOCNum");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_getOCNum: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 2: test_mopslib_photoS2N.
$g_start=new Benchmark;
ok(test_mopslib_photoS2N, "PS-MOPS-Lib_2->test_mopslib_photoS2N");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_photoS2N: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 3: test_mopslib_photoS2Nx.
$g_start=new Benchmark;
ok(test_mopslib_photoS2Nx, "PS-MOPS-Lib_2->test_mopslib_photoS2Nx");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_photoS2Nx: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 4: test_mopslib_astroError.
$g_start=new Benchmark;
ok(test_mopslib_astroError, "PS-MOPS-Lib_2->test_mopslib_astroError");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_astroError: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 5: test_mopslib_photoError.
$g_start=new Benchmark;
ok(test_mopslib_photoError, "PS-MOPS-Lib_2->test_mopslib_photoError");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_photoError: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 6: test_mopslib_fuzzRDM.
$g_start=new Benchmark;
ok(test_mopslib_fuzzRDM, "PS-MOPS-Lib_2->test_mopslib_fuzzRDM");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_fuzzRDM: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 7: test_mopslib_fuzzRDM2.
$g_start=new Benchmark;
ok(test_mopslib_fuzzRDM2, "PS-MOPS-Lib_2->test_mopslib_fuzzRDM2");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_fuzzRDM2: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 8: test_mopslib_fuzzRDM3.
$g_start=new Benchmark;
ok(test_mopslib_fuzzRDM3, "PS-MOPS-Lib_2->test_mopslib_fuzzRDM3");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_fuzzRDM3: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 9: test_mopslib_mutateControlObject.
$g_start=new Benchmark;
ok(test_mopslib_mutateControlObject, "PS-MOPS-Lib_2->test_mopslib_mutateControlObject");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_mutateControlObject: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 10: test_mopslib_mjd2nn.
$g_start=new Benchmark;
ok(test_mopslib_mjd2nn, "PS-MOPS-Lib_2->test_mopslib_mjd2nn");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_mjd2nn: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 11: test_mopslib_nn2mjd.
$g_start=new Benchmark;
ok(test_mopslib_nn2mjd, "PS-MOPS-Lib_2->test_mopslib_nn2mjd");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_nn2mjd: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 12: test_mopslib_mjd2localtimestr.
$g_start=new Benchmark;
ok(test_mopslib_mjd2localtimestr, "PS-MOPS-Lib_2->test_mopslib_mjd2localtimestr");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_mjd2localtimestr: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 13: test_mopslib_calculateDCriterion.
$g_start=new Benchmark;
ok(test_mopslib_calculateDCriterion, "PS-MOPS-Lib_2->test_mopslib_calculateDCriterion");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_calculateDCriterion: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 14: test_mopslib_V2filt.
$g_start=new Benchmark;
ok(test_mopslib_V2filt, "PS-MOPS-Lib_2->test_mopslib_V2filt");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_V2filt: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 15: test_mopslib_filt2V.
$g_start=new Benchmark;
ok(test_mopslib_filt2V, "PS-MOPS-Lib_2->test_mopslib_filt2V");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_filt2V: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 16: test_mopslib_effClassifyObjectNames.
$g_start=new Benchmark;
ok(test_mopslib_effClassifyObjectNames, "PS-MOPS-Lib_2->test_mopslib_effClassifyObjectNames");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_effClassifyObjectNames: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 17: test_mopslib_classifyObject.
$g_start=new Benchmark;
ok(test_mopslib_classifyObject, "PS-MOPS-Lib_2->test_mopslib_classifyObject");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_classifyObject: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 18: test_mopslib_hsn2flux.
$g_start=new Benchmark;
ok(test_mopslib_hsn2flux, "PS-MOPS-Lib_2->test_mopslib_hsn2flux");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_hsn2flux: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 19: test_mopslib_flux2hsn.
$g_start=new Benchmark;
ok(test_mopslib_flux2hsn, "PS-MOPS-Lib_2->test_mopslib_flux2hsn");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_flux2hsn: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 20: test_mopslib_mag2fluxsn.
$g_start=new Benchmark;
ok(test_mopslib_mag2fluxsn, "PS-MOPS-Lib_2->test_mopslib_mag2fluxsn");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_mag2fluxsn: " . timestr(timediff($g_end,$g_start),'all') . "\n";

# Test 21: test_mopslib_parseOrbfitOptsFile.
$g_start=new Benchmark;
ok(test_mopslib_parseOrbfitOptsFile, "PS-MOPS-Lib_2->test_mopslib_parseOrbfitOptsFile");
$g_end=new Benchmark;
print "time: PS-MOPS-Lib_2->test_mopslib_parseOrbfitOptsFile: " . timestr(timediff($g_end,$g_start),'all') . "\n";
