package ResultsParser;

use EvaluationResult;
use LocalConfig;



sub new {
    my ($class) = @_;
    my $self = {};
    bless $self, $class;
    return $self;
}



# the method parses the result file of QCS
# arg - either  EvaluationResult class or name of fileName
# 	or name of fileName 
sub parseQCS{
    my ($self, $arg) = @_;
    my $evalRes;    
    if (!defined($arg)){
	die "Missing required first argument in method parseQCS\n";
    }
    if ($arg->isa(EvaluationResult)){
	$evalRes = $arg;
    } else {
	$evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();
    my $infile = sprintf("%s/QCS/%s/%s.qcs", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
    open IN, "< $infile";
	while(defined(my $l = <IN>)){
		if ($l =~ m/^scores_for_model/){
			my @tokens = split(/\s+/, $l);
			my ($handedness, $contS, $qcs) = ($tokens[5], $tokens[6], $tokens[8]);
			$evalRes->{_scores}{contS} = sprintf("%.4f", $contS);
#			$evalRes->{_scores}{handedness} = sprintf("%.4f", $handedness);
			$evalRes->{_scores}{qcs} = sprintf("%.4f", $qcs);
			last;
 		}
	}
    close(IN);
    return $evalRes;
}

sub parseGrContS{
    my ($self, $arg) = @_;
    my $evalRes;
    if (!defined($arg)){
        die "Missing required first argument in method parseQCS\n";
    }
    if ($arg->isa(EvaluationResult)){
        $evalRes = $arg;
    } else {
        $evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();
    my $infile = sprintf("%s/GrContS/%s/%s.grconts", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
    open IN, "< $infile";
        my $l = <IN>;
        if ($l =~ m/^\S+\s+(\S+)/){
          $evalRes->{_scores}{contSintra} = sprintf("%.4f", $1);
	}
        
    close(IN);
    return $evalRes;
}


sub parseSOV{
    my ($self, $arg) = @_;
    my $evalRes;
    if (!defined($arg)){
	die "Missing required first argument in method parseSOV\n";
    }
    if ($arg->isa(EvaluationResult)){
        $evalRes = $arg;
    } else {
        $evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();
 
    my $infile = sprintf("%s/SOV/%s/%s.sov", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
    open IN, "< $infile";
        while(defined(my $l = <IN>)){
                if ($l =~ m/^SOV_NORMALIZED:\s+(\S+)/){
                        $evalRes->{_scores}{sov} = sprintf("%.4f", $1);
			last;
                }
        }
    close(IN);
    return $evalRes;
}


sub parseCE{
    my ($self, $arg) = @_;
    my $evalRes;
    if (!defined($arg)){
	die "Missing required first argument in method parseCE\n";
    }
    if ($arg->isa(EvaluationResult)){
        $evalRes = $arg;
    } else {
        $evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();

    my $infile = sprintf("%s/CE/%s/%s.ce", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
    open IN, "< $infile";
	my $nn_aa; # length of sequence, use d for normaliazation
        while(defined(my $l = <IN>)){
		if ($l =~ m/^Align\s+\S+\s+(\S+)/) {
			$nn_aa = $1;
		}
                if ($l =~ m/align-len\s+(\d+)\s+gaps\s+(\d+)/){
			my $total_align = $1; my $no_gaps = $2;
			if (defined($nn_aa) && $nn_aa != 0){
                        	$evalRes->{_scores}{ce_n_align} = sprintf("%.4f", 100.0*($total_align - $no_gaps)/$nn_aa);
			}
                }
		if ($l =~ m/^Z-score\s+(\S+)/){
			$evalRes->{_scores}{ce} = $1;
			last;
		}
        }
    close(IN);
    return $evalRes;
}

sub parseMammoth{
    my ($self, $arg) = @_;
    my $evalRes;
    if (!defined($arg)){
	die "Missing required first argument in method parseMammoth\n";
    }
    if ($arg->isa(EvaluationResult)){
        $evalRes = $arg;
    } else {
        $evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();

    my $infile = sprintf("%s/MAMMOTH/%s/%s.mammoth", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
    open IN, "< $infile";
	my $star_seq = '';
	my $pred_seq = '';
	my $exp_seq  = '';
	my $n = undef;
	my $trigger = 0;
        while(defined(my $l = <IN>)){
		chomp $l;
		if ($l =~ m/^==> PREDICTION/){
			$l = <IN>; $l = <IN>;
			$l = <IN>; chomp $l;
			if ($l =~ m/^\s+Number of residues:\s+(\d+)/){
				$n = $1;
			}
		}
                if ($l =~ m/^Z-score=\s+(\S+)\s+-ln\(E\)=\s+(\S+)/){
#                        $evalRes->{_scores}{mammoth} = sprintf("%.4f", $1);
			$evalRes->{_scores}{mammoth_ln_e} = sprintf("%.4f", $2);
                }
		if ($l =~ /Final Structural Alignment/){
			$trigger = 1;
			next;
		}
		if ($trigger == 1 && $l =~ m/\*/ && $l =~ m/^\s{11}[\*\s]+$/){
			$star_seq .= substr($l, 10);
			# Prediction CDWEEISVKG PNGESSVIHD RKSGKKFSIE EALQSGRLTP AHYDRYVNKD
			$l = <IN>;
			chomp $l;
			$pred_seq .= substr($l, 10);
			$l =<IN>; $l=<IN>; $l=<IN>;
			$l =<IN>;
			chomp $l;
			$exp_seq  .= substr($l, 10);
			$l=<IN>;
		}
        }
    close(IN);
    # calc alignment
    my $count = 0;
	for(my $i = 0; $i < length($pred_seq); $i++){
	   if (substr($star_seq,$i,1) eq '*'
        	&& substr($pred_seq,$i,1) eq substr($exp_seq,$i,1)
	        ){
        	        $count++;
	   }
	}
	if (defined($n) && $n != 0){
	  $evalRes->{_scores}{mammoth_n_align} = sprintf("%.4f", 100.0*$count/$n);
	} else {
	  $evalRes->{_scores}{mammoth_n_align} = sprintf("%.4f", 0.0);
	}

    return $evalRes;  
}


sub parseTMscore{
    my ($self, $arg) = @_;
    my $evalRes;
    if (!defined($arg)){
        die "Missing required first argument in method parseTMscore\n";
    }
    if ($arg->isa(EvaluationResult)){
        $evalRes = $arg;
    } else {
        $evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();

    my $infile = sprintf("%s/TMscore/%s/%s.tm", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
    open IN, "< $infile";
        my $star_seq = '';
        my $pred_seq = '';
        my $targ_seq  = '';
        my $n = undef;
        while(defined(my $l = <IN>)){
                chomp $l;
                if ($l =~ m/^Length of Chain_1:\s+(\d+)/){
                	$n = $1;
                }
                if ($l =~ m/^TM-score=\s+(\S+)\s+\(if normalized by length of Chain_1\)/){
                        $evalRes->{_scores}{tm} = sprintf("%.4f", $1);
                }
                if ($l =~ m/denotes aligned residue pairs of d/){
			$l = <IN>; chomp $l;
			$targ_seq = $l;
			$l = <IN>; chomp $l;
			$star_seq = $l;
			$l = <IN>; chomp $l;
			$pred_seq = $l;
			last;
                }
        }
    close(IN);
    # calc alignment
    my $count = 0;
        for(my $i = 0; $i < length($pred_seq); $i++){
           if (substr($star_seq,$i,1) eq ':'
                && substr($pred_seq,$i,1) eq substr($targ_seq,$i,1)
                ){
                        $count++;
           }
        }
        if (defined($n) && $n != 0){
          $evalRes->{_scores}{tm_n_align} = sprintf("%.4f", 100.0*$count/$n);
        } else {
          $evalRes->{_scores}{tm_n_align} = sprintf("%.4f", 0.0);
        }

    return $evalRes;
}


sub parseLGA_SDA{
    my ($self, $arg) = @_;
    my $evalRes;
    if (!defined($arg)){
	die "Missing required first argument in method parseLGA_SDA\n";
    }
    if ($arg->isa(EvaluationResult)){
        $evalRes = $arg;
    } else {
        $evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();

    my $infile = sprintf("%s/LGA/SDA/DATA/%s/%s.lga", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
        open IN, "< $infile";
        while(defined(my $l = <IN>)){
                if ($l =~ m/^SUMMARY\(GDT\)\s+(\S+)\s+\S+\s+\S+\s+(\S+)\s+\S+\s+(\S+)/){
			my $no_res = $1; 
			my $no_align = $2;
			my $gdt_ts = $3;
			$evalRes->{_scores}{lga_gdt_ts} = sprintf("%.4f", $gdt_ts);
			last;
                }
        }
    close(IN);
    return $evalRes;
}

sub parseLGA_SIA{
    my ($self, $arg) = @_;
    my $evalRes;
    if (!defined($arg)){
        die "Missing required first argument in method parseLGA_SDA\n";
    }
    if ($arg->isa(EvaluationResult)){
        $evalRes = $arg;
    } else {
        $evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();
    my $no_align = 0;
    my $infile = sprintf("%s/LGA/SIA_5/DATA/%s/%s.lga", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
        open IN, "< $infile";
        while(defined(my $l = <IN>)){
		if ($l =~ m/^LGA/){
			my @tokens = split(/\s+/, $l);
			if ($tokens[2] ne '-' && $tokens[2] eq $tokens[4] && $tokens[5] ne '#'){
				$no_align++;
			}
		}
                if ($l =~ m/^SUMMARY\(LGA\)\s+\S+\s+(\S+)\s+\S+\s+\S+\s+\S+\s+\S+/){
                        my $no_res = $1;
                        $evalRes->{_scores}{lga_n_align} = sprintf("%.4f", 100.0*$no_align/$no_res);
                        last;
                }
        }
    close(IN);
    return $evalRes;
}

sub parseDali {
    my ($self, $arg) = @_;
    my $evalRes;
    if (!defined($arg)){
        die "Missing required first argument in method parseDali\n";
    }
    if ($arg->isa(EvaluationResult)){
        $evalRes = $arg;
    } else {
        $evalRes = new EvaluationResult($arg);
    }
    my $model = $evalRes->createModelName();
    my $target = $evalRes->createTargetName();

    my $infile = sprintf("%s/DaliLite/%s/%s/index.html", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
        open IN , "< $infile";
	my  $no_res; my $no_align; my $dali; my $perc;
	while(defined(my $l = <IN>)){
		if ($l =~ m/^<TD>\S+<\/TD><TD>mol2.{0,1}<\/TD><TD>(\-{0,1}[0-9]+\.[0-9]+)<\/TD><TD>([0-9]+)<\/TD><TD>\-{0,1}[0-9]+\.[0-9]+<\/TD><TD>(\S+)<\/TD>/){
			#$dali = $1; 
			$no_align = $2; $perc = $3;
		}
		
		if ($l =~ m/^mol1:\s+(\S+)\s+/){
			$no_res = $1;
			last;
		}
	}
	close IN;
	if (defined($no_align) && defined($no_res) && $no_res != 0 && defined($perc)){
		$evalRes->{_scores}{dali_n_align} = sprintf("%.4f", $perc*$no_align/$no_res);
		$evalRes->{_scores}{dali} = sprintf("%.4f", $dali);
	} else {
		$evalRes->{_scores}{dali_n_align} = undef;
		$evalRes->{_scores}{dali} = undef;
	}
	$infile = sprintf("%s/DaliLite/%s/%s/mol1.dccp", $LOCAL_CONFIG->{RESULTS_DIR}, $target, $model);
	if (open(IN, $infile)){
		my $l = <IN>;
		if ($l =~ m/^\s*DCCP\s+\S+\s+(\S+)/){
			my $dali_raw = $1;
			if ($dali_raw =~ m/^([0-9]+\.[0-9])/){
				$dali_raw = $1;
				$evalRes->{_scores}{dali} = $dali_raw;
			}
		}
		close(IN);
	}
     return $evalRes;                
}


1;
