#!/usr/bin/perl -w

use strict;

my %hash;#Hash on ho guardarem tot.
my $n = 0;#Variable per comptar línies.
my $i = -1; #Variable per les matrius.
my @k;
my @v;
my $nom;
my $As = 0;
my $Cs = 0;
my $Gs = 0;
my $Ts = 0;
my $total = 0;
my $compta=0;



open(FITXERMEU,"< $ARGV[0]"); #Perque t'agafi el primer arxiu que li dones al terminal.

my $ch=0;

my $promotor;

open(FITXERDOS,"< $ARGV[1]");#Perque t'agafi el segon arxiu que li dones al terminal.

while(<FITXERDOS>){#Perque et transformi la sequencia de format FASTA a una sola línia i te la guardi a una variable.
    
    $ch = $ch + 1;

    if ($ch > 1){

	chomp($_);

	$promotor = $promotor . $_;

    }

}

close(FITXERDOS);

my @vectorpromotor = split(//,$promotor); #Et fica cadascuna dels nucleotids del promotor en una posició d'un vector. 

my $lenght = scalar(@vectorpromotor); #Calcula la longitud del vector on hi ha el promotor.

my $w = 0;

while ($w < $lenght){ #Tot això calcula quantes As,Cs, Gs i Ts hi ha dins del promotor per fer-ho servir més endavant.

    if ( $vectorpromotor[$w] eq 'A'){

	$As = $As + 1;

    }

    elsif ( $vectorpromotor[$w] eq 'C'){

	$Cs = $Cs + 1;

    }

    elsif ( $vectorpromotor[$w] eq 'G'){

	$Gs = $Gs + 1;

    }

    elsif ( $vectorpromotor[$w] eq 'T'){

	$Ts = $Ts + 1;

    }

    $w = $w + 1;

} 

$total = $As+$Cs+$Gs+$Ts;

while (<FITXERMEU>){    

    my @vectorpromotor = split(//,$promotor);#Et fica el promotor dins d'un vector, ja que quant fas el vector random es desordena. 
 	                                     #D'aquesta manera tornes a tenir el promotor original. 

    $n = $n + 1; #Compta les línies del primer fitxer. 

    chomp($_);
    @v = split(//,$_); #Et fica en un vector cada línia que llegeix del primer fitxer.

    if ($v[0] eq 'F' && $v[1] eq 'A'){ #Si el que hi ha al vector és una F i després una A, guarda el que hi ha a la línia com a nom.

	$nom = $_;

    }
           
    if (m/[\s]+(\d+)[\s]+(\d+)[\s]+(\d+)[\s]+(\d+)[\s]*/){ #Si el que llegeix a la linia del fitxer és la fila dels valors, guarda 
	                                                   #aquests valors al hash.
	
	$i = $i+1 ; #Avança la posició del hash en què col·loca.
	
	$hash{A}[$i] = $1; #Com que els valors sempre surten en el mateix ordre podem aprofitar aquest fet per guardar sempre en el mateix
	$hash{C}[$i] = $2; #ordre.
	$hash{G}[$i] = $3;
	$hash{T}[$i] = $4;

	$compta= $1+$2+$3+$4; #Compta el número de sequències analitzades

    }

    if ($v[0] eq '/' && $n > 7 && $n < 152){ #Si el que llegeix és una barra i el número de línies és superior a 7 i inferior a 152 farà 
	                                     #el següent. Superior a 7 perquè al principi hi ha una barra i inferior a 152 perquè la última
	                                     #línia torna a ser una barra.

	@k = keys(%hash); #Per tenir les paraules claus del hash en un vector.

	@k = sort(@k); #Ordena les paraules claus del hash. 

	$i = 0;
       
	while ($i < scalar(@k)) { #Recorre el hash a cada posició.
	    
	    my $dist = scalar(@{$hash{$k[$i]}});

	    my $j = 0;
	    
	    while ($j < $dist) {

		if ($hash{$k[$i]}[$j] == 0){ #Si el valor que hi ha a la posició del hash és 0 no calcula el log i fica -999.

		    $hash{$k[$i]}[$j] = -999;
		
		} #El primer logaritme és el de la  proporció d'ocurrències del nucleòtid x a la posició i del hash. 
		  #El segon logaritme és la proporció d'ocurrències del nucleòtid x al llarg de tota la seqüència promotora.

		elsif ( $k[$i] eq 'A') {

		    $hash{$k[$i]}[$j] = (  log(($hash{$k[$i]}[$j])/$compta) - log( $As/$lenght ));

		}

		elsif ( $k[$i] eq 'C') {

		    $hash{$k[$i]}[$j] = (  log(($hash{$k[$i]}[$j])/$compta) - log( $Cs/$lenght ));

		}

		elsif ( $k[$i] eq 'G') {

		    $hash{$k[$i]}[$j] = (  log(($hash{$k[$i]}[$j])/$compta) - log( $Gs/$lenght ));

		}
		
		elsif ( $k[$i] eq 'T') {

		    $hash{$k[$i]}[$j] = (  log(($hash{$k[$i]}[$j])/$compta) - log( $Ts/$lenght ));

		}

		$j = $j + 1; #Avança columnes de la paraula clau que mires.
	    }
	    	    
	    $i = $i + 1; #Avança la paraula clau que mires.

	}

	my $p = -1; #Mira la posició del promotor. 

	my $scoremaxim = -99999999999999999999999999999999999999; #Scoremàxim molt petit per evitar que hi hagi scores que no es queda.

	my $posicioscore; #Guarda la posició de l'score.

	my $posicioultimascore;

	@k = keys(%hash);

	@k = sort(@k);
	
	$i = 0;
	
	my $d = -1;

	my $dist = scalar(@{$hash{$k[$i]}});

	my $sequenciamax;

	while ($p < (($lenght-1)-$dist+1)){ #Recorre tot el promotor menys la distància del motiu. 

	    $p = $p + 1;#Avança la posició del promotor que mires. 
 
	    $d = $d + 1; #Variable que serveix per guardar la posició que mirem, ja que després avancem la p. 

	    my $x = 0; #Comença a la posició 0 del motiu. 

	    my $score = 0; #Fica l'score a 0.

	    my $sequencia;

	    while ($x < ($dist)){ #Recorre el promotor fins que arriba a la distància del motiu i va sumant els scores corresponents. 

		$score = $score + ($hash{$vectorpromotor[$p]}[$x]);

		$sequencia = $sequencia . $vectorpromotor[$p];

		$x = $x + 1; #Avança la posició del motiu que toca. 

		$p = $p + 1; #Avança la posició del promotor. 
		
	    }
	    
	    $p = $d; #Fa que p torni a ser el valor que era abans de fer el càlcul de l'score. 

	    if ($score > $scoremaxim){ #Si l'score és superior a l'scoremaxim guarda l'score com a scoremaxim i guarda la posició. 

		$scoremaxim = $score;

		$posicioscore = $d;#Guarda la primera posició de l'scoremaxim.

		$posicioultimascore = $d + ($dist-1);#Guarda la última posició de l'scoremàxim.

		$sequenciamax = $sequencia;#Guarda la seqüència de l'scoremaxim. 
		
	    }    
    	
      
	}

	print "$scoremaxim\t"; #Imprimeix l'scoremaxim. 
	
	my $z = 0;

	my $resultat = 0;

	while ($z < 100){ #Fa el procés 100 cops.

	    $z = $z + 1;

	    my $n = $lenght-1;
	        
	    my $i = $n - 1;

	    while ($i >= 0) { #Permuta el vector on hi ha el promotor. 
		
		my $j = int(rand($i+1));

		if ($i != $j) {

		    my $tmp = $vectorpromotor[$i];
		    
		    $vectorpromotor[$i] = $vectorpromotor[$j];

		    $vectorpromotor[$j] = $tmp;

		}

		$i = $i - 1;

	    }

	    my $p = -1; #A partir d'aqui torna a fer el mateix d'abans però amb el vector que has permutat.

	    my $scoreatzar = -99999999999999999999999999999999999999;

	    my $posicioscore;

	    @k = keys(%hash);

	    @k = sort(@k);
	
	    $i = 0;
	
	    my $d = -1;

	    my $dist = scalar(@{$hash{$k[$i]}});

	    while ($p < (($lenght-1)-$dist+1)){

		$p = $p + 1;

		$d = $d + 1;
		
		my $x = 0;
		
		my $score = 0;

		while ($x < ($dist)){

		    $score = $score + ($hash{$vectorpromotor[$p]}[$x]);
   
		    $x = $x + 1;

		    $p = $p + 1;
		
		}
	    
		$p = $d;

		if ($score > $scoreatzar){

		    $scoreatzar = $score;

		    $posicioscore = $d;
		
		}    
    	
	    }

	    if ($scoreatzar > $scoremaxim){ #Si l'score que trobes per atzar és superior que el que tens com a màxim, suma 1 al resultat.

		$resultat = $resultat + 1;

	    }

	}

	my $pvalue = $resultat/100; #Divideix els cops que ha trobat un score per atzar superior al màxim per 100. Això li diem p-value. 

	print "$pvalue\t$nom\t$posicioscore\t$posicioultimascore\t$sequenciamax\n"; #Imprimeix el p-value, el nom, la 1º posicio i la última                                                                                    #de l'scoremaxim i la seqüència. 

	$i = -1;

	%hash = (); #Reinicia el hash. 

    }
       
}


close(FITXERMEU);

