#!/opt/anaconda1anaconda2anaconda3/bin/perl 

use warnings;
use strict "vars";
use strict "refs";

use FindBin;
use lib "$FindBin::RealBin/../lib";
use lib "$FindBin::RealBin/../perl/lib";
use vars qw($RANK $LOG $CMD_ARGS);

BEGIN{
   if (not ($ENV{CGL_SO_SOURCE})) {
      $ENV{CGL_SO_SOURCE} = "$FindBin::RealBin/../lib/CGL/so.obo";
   }
   if (not ($ENV{CGL_GO_SOURCE})) {
      $ENV{CGL_GO_SOURCE} = "$FindBin::RealBin/../lib/CGL/gene_ontology.obo"
   }
   
   $CMD_ARGS = join(' ', @ARGV);
   
   #what to do on ^C
   $SIG{'INT'} = sub {
      print STDERR "\n\nAborted by user!!\n\n";
      exit (1);
   };    
   
   #supress warnings from storable module
   $SIG{'__WARN__'} = sub {
      warn $_[0] if ( $_[0] !~ /Not a CODE reference/ &&
		      $_[0] !~ /Can\'t store item /
		    );
   };

   #output to log file of seq that caused rank to die
   $SIG{'__DIE__'} =
   sub {
      if (defined ($LOG) && defined $_[0]) {
	 my $die_count = $LOG->get_die_count();
	 $die_count++;
	 
	 $LOG->add_entry("DIED","RANK",$RANK);
	 $LOG->add_entry("DIED","COUNT",$die_count);
      }

      die $_[0]."\n".
	  "FATAL ERROR\n";
   };
}

use Cwd;
use FileHandle;
use File::Path;
use Getopt::Long qw(:config no_ignore_case);
use File::Temp qw(tempfile tempdir);
use GI;
use Dumper::GFF::GFFV3;
use Iterator::Any;
use Iterator::Fasta;
use Iterator::GFF3;
use Fasta;
use FastaChunker;
use maker::auto_annotator;
use cluster;
use repeat_mask_seq;
use runlog;
use ds_utility;
use GFFDB;
use Error qw(:try);
use Error::Simple;
use Process::MpiChunk;
use Process::MpiTiers;

$| = 1;

my $usage = "
Usage:

     map2assembly <genome.fasta> <transcripts.fasta>

     Maps old gene models to a new assembly where possible.


Option:

     -cpus|c  <integer>  Tells how many cpus to use for BLAST analysis.

     -retry|r <integer>  Rerun failed contigs up to the specified count.

     -force|f            Delete old files before running again.

     -again|a            Run again without deleting files.

     -quiet|q            Silences most status messages.

     -help|?             Prints this usage statement.


";

#-------------------------------------------------------------------------------
#------------------------------------ MAIN -------------------------------------
#-------------------------------------------------------------------------------

#---global variables
my %OPT;
my $rank = 0;
my $size = 1;
$RANK = $rank;
GI::RANK($rank);
$OPT{tries} = 3;

#---Process options on the command line 
try{
    GetOptions("cpus|c=i" => \$OPT{cpus},
	       "protein|p=s" => \$OPT{protein},
	       "force|f" => \$OPT{force},
	       "retry=i" =>\$OPT{retry},
	       "again|a" =>\$OPT{again},
	       "qq"    =>\$main::qq,
	       "quiet" =>\$main::quiet,
	       "help|?" => sub {print $usage; exit(0)}
	       );
    $main::quiet = 1 if($main::qq);
}
catch Error::Simple with{
    my $E = shift;
    
    print STDERR $E->{-text};
    die "\n\nFailed while parsing command line options!!\n\n";
};

#varibles that are persistent outside of try
my %CTL_OPT;
my $iterator;
my $DS_CTL;
my $GFF_DB;
my $g_index;
my $build;
my @failed;
my @interrupted;

try{
    my $genome      = shift @ARGV;
    my $transcripts = shift @ARGV;

    if (! $genome || ! $transcripts) {
	print STDERR  "ERROR: Input files not provided\n";
	print $usage;
	exit(1);
    }

    #--load special options for CTL_OPT integration
    $OPT{genome}         = $genome;
    $OPT{est2genome}     = 1;
    $OPT{est}            = $transcripts;
    $OPT{est_forward}    = 1;
    $OPT{max_dna_len}    = 300000;
    $OPT{split_hit}      = 30000;
    $OPT{pred_flank}     = 1000;
    $OPT{single_exon}    = 1;
    $OPT{single_length}  = 1;
    $OPT{pcov_blastn}    = .70;
    $OPT{pid_blastn}     = .70;
    $OPT{pcov_blastx}    = .50;
    $OPT{pid_blastx}     = .60;
    $OPT{en_score_limit} = 20;
    $OPT{ep_score_limit} = 10;
    $OPT{R}              = 1;
    $OPT{blast_type}              = 'ncbi+';
    #--Control file processing
   
    #set up control options from control files
    %CTL_OPT = GI::load_control_files([], \%OPT, $size);
    GI::new_instance_temp($CTL_OPT{TMP});

    #--open datastructure controller
    $DS_CTL = ds_utility->new(\%CTL_OPT);
    
    #--set up gff database
    $GFF_DB = new GFFDB(\%CTL_OPT);
    $build = $GFF_DB->next_build;

    #--set up blast databse
    GI::create_blastdb(\%CTL_OPT);
    my $gdbfile = $CTL_OPT{_g_db}[0];
    $g_index = GI::build_fasta_index([$gdbfile]);
    
    #---load genome multifasta/GFF3 file
    $iterator = new Iterator::Any( -fasta => $CTL_OPT{'genome'},
				   -gff => $CTL_OPT{'genome_gff'},
				   );
    $iterator->step($CTL_OPT{'_step'});
}
catch Error::Simple with{
    my $E = shift;
    print STDERR $E->{-text};
    #print STDERR "\n\nMaker failed while examining startup data\n",
    #"(control files and input fasta files)!!\n\n";
    my $code = 2;
    $code = $E->{-value} if (defined($E->{-value}));
    
    exit($code);
};

my $tier;
my $i_count = @interrupted;
my $f_count = @failed;
while (my $q_def = $iterator->nextDef || shift @failed || shift @interrupted){
    $tier = Process::MpiTiers->new({q_def => $q_def,
				    g_index => $g_index,
				    CTL_OPT => \%CTL_OPT,
				    DS_CTL  => $DS_CTL,
				    dbfile  => $GFF_DB->dbfile,
				    build   => $build},
				   '0',
				   'Process::MpiChunk'
				   );

    next if($tier->terminated);

    #take a short break before processing previously failed contigs
    #this handles heavy processor usage when failure is related
    #to maker process overlap
    sleep 1 if($f_count != @failed);

    $tier->run_all(0);

    push(@failed, $tier->fasta) if ($tier->failed);
    push(@interrupted, $tier->fasta) if ($tier->interrupt && $i_count == @interrupted);

    $f_count = @failed; #reset failure count
    $i_count = @interrupted; #reset interrupt count
}

#merge gff3 files into big file
print STDERR "\n\nBuilding final GFF3 file.\n\n";
system("$FindBin::RealBin/gff3_merge -g -d ".$DS_CTL->get_index);

if($?){
    die "ERROR: Failed while trying to build final GFF3 file\n\n";
}

print STDERR "\n\nNow Finished!!!\n\n";


#-----------------------------------------------------------------------------
#----------------------------------- SUBS ------------------------------------
#-----------------------------------------------------------------------------
