#!/usr/bin/perl -w

#use strict;

my (@tmplist, $data_file, $quorum, @lmin, @lmax, @e, $blocs, $curbloc,
    $i, @compo, @flag_compo, @saut_min, @saut_max, @comline, $output_file,
    $prog, $ok, $shufflings, @comline2, @delta, $flag_delta, $ordre, $contre,
    @symbcompo, $alpha_file);

# Chemin des programmes executable ##############################################
$prog1 = "../bin/max_extensibility";
$prog2 = "../bin/max_extensibility";
$progstat = "../bin/e-smile_shuffling";
$progfaux = "../bin/e-smile_against";

# Fichier de noms de fichiers generes ##########################################
$namefile = ".namefile";

print "\n****************************************************@comline";
print "\n**************  RISO-ME (version 1.0)  *************@comline";
print "\n****************************************************@comline\n";

if ( !@ARGV )
    {
    print "\nUsage: riso [ <parameter file> | -g <nb> ]\n";
    print "\t\t-g <nb> print a generic parameter file for <nb> boxes\n\n";
    exit;
    }


## Generation du fichier type #################################################
if ( $ARGV[0] eq "-g" )
    {
    $blocs = $ARGV[1];

    if (!$blocs || !($blocs =~ /^\d+$/) || $blocs <= 0 )
        {
        print "\nUsage: riso [ <parameter file> | -g <nb> ]\n";
        print "\t\t-g <nb> print a generic parameter file for <nb> boxes\n\n";
        exit;
        }

    print "\nEXTRACTION =========================================\n";
    print "FASTA file\t\t\tfile_name\n";
    print "Output file\t\t\tfile_name_out\n";
    print "Alphabet file\t\t\tfile_name_alphabet\n";
    print "Quorum\t\t\t\t0\n";
    print "Boxes\t\t\t\t$blocs\n\n";

    $i = 1;
    while ( $i <= $blocs )
        {
	print "BOX $i ============================\n";
        print "Min length\t\t\t0\n";
        print "Max length\t\t\t0\n";
        print "Substitutions\t\t\t0\n";

        unless ( $i == $blocs )
            {
            print "Min spacer length\t\t0\n";
            print "Max spacer length\t\t0\n";
            #---TODO--- print "Delta\t\t\t\t0\n\n";
            }
        $i++;
        }
	print "\n";

#    print "\n\nEVALUATION (Step 2) ===================================================\n";
#    print "Shufflings\t\t\t100\n";
#    print "Size k-mer\t\t\t0\n";
#    print "      OR\n";
#    print "Against wrong sequences\t\tfile_name_wrong_seqs\n\n";
    exit;
    }
###############################################################################
    
-r "$ARGV[0]" or print "$ARGV[0] is not readable!\n" and exit;
open(FILE,"$ARGV[0]");

while ( <FILE> )
    {

    if ( /FASTA file/ )
        {
        @tmplist = split(" ");
        $data_file = $tmplist[2];

        -r "$data_file" or print "Line $.: $data_file is not readable!\n" and exit;
        }
    elsif ( /Output file/ )
        {
        @tmplist = split(" ");
        $output_file = $tmplist[2];
        }
    elsif ( /Alphabet file/ )
        {
        @tmplist = split(" ");
        $alpha_file = $tmplist[2];
        }
    elsif ( /Quorum/ )
        {
        @tmplist = split(" ");
        $quorum = $tmplist[1];
        }
    elsif ( /Total min length/ )
        {
        @tmplist = split(" ");
        $lmin[0] = $tmplist[3];
        }
    elsif ( /Total max length/ )
        {
        @tmplist = split(" ");
        $lmax[0] = $tmplist[3];
        }
    elsif ( /Total substitutions/ )
        {
        @tmplist = split(" ");
        $e[0] = $tmplist[2];
        }
    elsif ( /Boxes/ )
        {
        @tmplist = split(" ");
        $blocs = $tmplist[1];

        if($blocs <= 0)
            { print "Line $.: incorrect number of boxes.\n" and exit; }
        }
    elsif ( /Shufflings/ )
        {
        @tmplist = split(" ");
        $shufflings = $tmplist[1];
        }
    elsif ( /Size k-mer/ )
        {
        @tmplist = split(" ");
        $ordre = $tmplist[2];
        }
    elsif ( /Against wrong sequences/ )
        {
        @tmplist = split(" ");
        $contre  = $tmplist[3];
        }
    elsif ( /BOX/ )
        {
        @tmplist = split(" ");
        $curbloc = $tmplist[1];

        if ( ! defined($blocs) )
            { print "Line $.: no number of boxes has been defined before\n" and exit; }

        if ( (!$curbloc) || ($curbloc <= 0) || ($curbloc > $blocs) )
            { print "Line $.: incorrect box number\n" and exit; }

        while ( defined($line = <FILE>) && ($line ne "\n") )
            {
            if ( $line =~ /Min length/ )
                {
                @tmplist = split(" ", $line);
                $lmin[$curbloc] = $tmplist[2];
                }
            elsif ( $line =~ /Max length/ )
                {
                @tmplist = split(" ", $line);
                $lmax[$curbloc] = $tmplist[2];
                }
            elsif ( $line =~ /Substitutions/ )
                {
                @tmplist = split(" ", $line);
                $e[$curbloc] = $tmplist[1];
                }
            elsif ( $line =~ /Min spacer length/ )
                {
                if ( $curbloc == $blocs )
                    { print "Line $.: the last box can't have jump parameters\n"; }

                @tmplist = split(" ", $line);
                $saut_min[$curbloc] = $tmplist[3];
                }
            elsif ( $line =~ /Max spacer length/ )
                {
                if ( $curbloc == $blocs )
                    { print "Line $.: the last box can't have jump parameters\n"; }

                @tmplist = split(" ", $line);
                $saut_max[$curbloc] = $tmplist[3];
                }
            elsif ( $line =~ /Delta/ )
                {
                if ( $curbloc == $blocs )
                    { print "Line $.: the last box can't have a delta parameter\n"; }

                @tmplist = split(" ", $line);
                $delta[$curbloc] = $tmplist[1];
                $flag_delta      = 1;
                }
            elsif ( $line =~ /Composition/ )
                {
                if( !defined($flag_compo[$curbloc]))
                    { $flag_compo[$curbloc] = 0; }
                @tmplist = split(" ", $line);
                $symbcompo[$curbloc][$flag_compo[$curbloc]]="$tmplist[2]";
                $compo[$curbloc][$flag_compo[$curbloc]] = $tmplist[3];
                $flag_compo[$curbloc] += 1;
                }
            else
                { 
                chomp($line);
                #print "Line $.: box parameter ignored: \"$line\"\n";
                }
                
            }
        }
    elsif ( /Composition/ )
        {
        if( !defined($flag_compo[0]))
            { $flag_compo[0] = 0; }
        @tmplist = split(" ");
        $symbcompo[0][$flag_compo[0]] = "$tmplist[2]";
        $compo[0][$flag_compo[0]] = $tmplist[3];
        $flag_compo[0] += 1;
        }
    elsif ( ! /^\n$/ )
        {
        chomp;
        #print "Line $. ignored : \"$_\"\n";
        }
    }


# Verification et preparation des parametres ##################################
if ( !defined($alpha_file) )
    { print "Alphabet file hasn't been defined!\n(Add an 'Alphabet file' line to your parameter file)\n" and exit; }
if ( !defined($data_file) )
    { print "Fasta file hasn't been defined!\n(Add a 'FASTA file' line to your parameter file)\n" and exit; }
if ( !defined($output_file) )
    { print "Output file hasn't been defined!\n(Add an 'Output file' line to your parameter file)\\n" and exit; }
if ( !defined($quorum) || $quorum <= 0 || $quorum > 100 )
    { print "Quorum is incorrect or not defined.\n(Add a 'Quorum' line to your parameter file. It's a percentage)\n" and exit; }
#if ( !defined($lmin[0]) || $lmin[0] <= 0 )
#    { print "Total min length is incorrect or not defined.\n(Add a 'Total min length' line to your parameter file)\n" and exit; }
#if ( !defined($lmax[0]) || ( ( $lmax[0] != 0) && ($lmax[0] < $lmin[0] ) ) )
#    { print "Total max length is incorrect or not defined.\n(Add a 'Total max length')\n" and exit; }
#if ( !defined($e[0]) || $e[0] < 0 || ( ($lmax[0] != 0) && ($e[0] >= $lmax[0]) ) )
#    { print "Total substitions number is incorrect or not defined.\n(Add a 'Total substitutions' line to your parameter file)\n" and exit; }
if ( !defined($ordre) && defined($shufflings))
    { print "The shuffling order hasn't been defined.\n(Add a 'Size k-mer' line to your parameter file)\n" and exit; }
if ( defined($ordre) && defined($shufflings) && $shufflings != 0 && $ordre <1)
    { print "Shuffling order must be greater than 0.\n", and exit; }
if ( defined($contre) && (defined($ordre) || defined($shufflings) ) )
    { print "Shuffling and Against methods are not compatible.\n" and exit; }

if (!defined ($blocs))
    { printf "Number of boxes is incorrect or not defined.\n(Line 'Boxes')\n" and exit; }

if( $blocs >= 1 )
    {
    for ($i=1; $i <= $blocs; $i++)
        {
        if ( !defined($lmin[$i]) || $lmin[$i] < 2 )
            { print "Min length for box $i is incorrect or not defined.\n(Line 'Min length')\n" and exit; }
        if ( !defined($lmax[$i]) || $lmax[$i]<$lmin[$i] )
            { print "Max length for box $i is incorrect or not defined.\n(ligne 'Max length')\n" and exit; }
        if ( !defined($e[$i]) || $e[$i]<0 || $e[$i]>=$lmax[$i] )
            { print "Substitutions number for box $i is incorrect or not defined.\n(Line 'Substitutions')\n" and exit; }
        if ( $blocs != 1 && $i != $blocs && (!defined($saut_min[$i]) || $saut_min[$i]<0) )
            { print "Min jump for box $i is incorrect or not defined.\n(Line 'Min spacer length')\n" and exit; }
        if ( $blocs != 1 && $i != $blocs && (!defined($saut_max[$i]) || $saut_max[$i]<$saut_min[$i]) )
            { print "Max jump for box $i is incorrect or not defined.\n(Line 'Max spacer length')\n" and exit; }

        if ( defined($flag_delta) && $blocs != 1 && $i != $blocs )
            {
            if (defined($delta[$i]))
                {
                if ( $delta[$i] < 0 || $saut_max[$i]-$saut_min[$i] < $delta[$i]*2 )
                    { print "Delta for bloc $i is incorrect : not compatible with spacer range.\n(Line 'Delta')\n"
                    and exit; }
                }
            else
                {print "Box $i has no delta and another box has one.\n(Line 'Delta'. Fix a delta equal to the spacer range if you don't want to use it for this box.)\n"
                and exit;}
            }
        }
    }


# LANCEMENT DU PROGRAMME ######################################################
-r $data_file or print "$data_file is not readable!\n" and exit;

if (defined($flag_delta))
    { @comline = ($prog2); }
else
    { @comline = ($prog1); }

push @comline, ($alpha_file,$data_file,$output_file,$quorum,$blocs);

if ($blocs >= 1)
    {
    for ($i=1; $i<$blocs; $i++)
        {
        push @comline, ($lmin[$i],$lmax[$i],$e[$i]);

	if ($blocs > 1) 
	    {push @comline, ($saut_min[$i],$saut_max[$i]);}
        
        if (defined($flag_delta))
            {push @comline, ($delta[$i]);}
        }
    push @comline, ($lmin[$i],$lmax[$i],$e[$i]);
    }

print "\nCalling RISO-ME with \n@comline\n\n";

$ok = system @comline;

if ( $ok != 0 )
    { print "Error during execution of extraction (code $ok)\n";
      if($ok == 65280)
        { print "You didn't fully compile RISO. Type 'make' in the parent directory.\n" and exit}
    
      exit;
    }

suite:

## FAUX ####################################
if( defined($contre) )
    {
    $comline2[0] = $progfaux;
    $comline2[1] = $contre;
    $comline2[2] = $output_file;
    $comline2[3] = $output_file.".against";

    if (defined($flag_delta))
        {
        -r $namefile or print "$namefile is not readable!\n" and exit;

        open(NAMEFILE,$namefile);

        while ( defined($line = <NAMEFILE>) )
            {
            chomp($line);
            $comline2[2] = $line;
            $comline2[3] = $line.".against";

            -r $line or print "$line is not readable!\n" and exit;

            print "\n*** AGAINST '$line'\n@comline2\n";

            if ( -e "$comline2[3]" )
                {
                print "WARNING! '$comline2[3]' already exists!\n";
                print "Type 'ok' to continue...\n";
                $i = <STDIN>;
                chomp($i);
                if ($i ne "ok")
                    { print "Execution interrupted.\n" and exit; }
        
                unless ( -w "$comline2[3]" )
                    { print "'$comline2[3]' is not writable!\n" and exit; } 
                }

            $ok = system @comline2;

            if ( $ok != 0 )
                { print "Error during execution of evaluation (code $ok)\n";
                  if($ok == 65280)
                    { print "You didn't fully compile SMILE. Type 'make' in the parent directory.\n" and exit}
                exit;
                }
            }
        exit;
        }


    print "\n*** AGAINST '$comline2[1]'\n@comline2\n";

    -r $contre or print "$contre is not readable!\n" and exit;
    if ( -e "$comline2[3]" )
        {
        print "WARNING! '$comline2[3]' already exists!\n";
        print "Type 'ok' to continue...\n";
        $i = <STDIN>;
        chomp($i);
        if ($i ne "ok")
            { print "Execution interrupted.\n" and exit; }
        
        unless ( -w "$comline2[3]" )
            { print "'$comline2[3]' is not writable!\n" and exit; } 
        }
    
    $ok = system @comline2;
    
    if ( $ok != 0 )
        { print "Error during execution of evaluation (code $ok)\n";
          if($ok == 65280)
            { print "You didn't fully compile SMILE. Type 'make' in the parent directory.\n" and exit}
          exit;
        }

    }




if ( !defined($shufflings) || $shufflings == 0 )
    { exit; }

# STATS ###########################
$comline2[0] = $progstat;
$comline2[1] = $data_file;
$comline2[2] = $output_file;
$comline2[3] = $output_file.".shuffle";
$comline2[4] = $shufflings;
$comline2[5] = $ordre;

if (defined($flag_delta))
    {
    -r $namefile or print "$namefile is not readable!\n" and exit;

    open(NAMEFILE,$namefile);

    while ( defined($line = <NAMEFILE>) )
        {
        chomp($line);
        $comline2[2] = $line;
        $comline2[3] = $line.".shuffle";

        -r $line or print "$line is not readable!\n" and exit;

        print "\n*** SHUFFLING '$line'\n@comline2\n";

        if ( -e "$comline2[3]" )
           {
            print "WARNING! '$comline2[3]' already exists!\n";
            print "Type 'ok' to continue...\n";
           $i = <STDIN>;
           chomp($i);
           if ($i ne "ok")
               { print "Execution interrupted.\n" and exit; }
       
            unless ( -w "$comline2[3]" )
                { print "'$comline2[3]' is not readable!\n" and exit; } 
           }

        $ok = system @comline2;
    
        if ( $ok != 0 )
            { print "Error during execution of evaluation (code $ok)\n";
              if($ok == 65280)
                { print "You didn't fully compile SMILE. Type 'make' in the parent directory.\n" and exit}
              exit;
            }
        }
    exit;
    }


print "\n*** SHUFFLING '$comline2[2]'\n@comline2\n";
-r $output_file or print "$output_file is not readable!\n" and exit;
if ( -e "$comline2[3]" )
    {
    print "WARNING! '$comline2[3]' already exists!\n";
    print "Type 'ok' to continue...\n";
    $i = <STDIN>;
    chomp($i);
    if ($i ne "ok")
        { print "Execution interrupted.\n" and exit; }
        
    unless ( -w "$comline2[3]" )
        { print "'$comline2[3]' is not writable!\n" and exit; } 
    }
    
$ok = system @comline2;
    
if ( $ok != 0 )
    { print "Error during execution of evaluation (code $ok)\n";
      if($ok == 65280)
        { print "You didn't fully compile SMILE. Type 'make' in the parent directory.\n" and exit}
      exit;
    }
