package MultimerResultsUploadManager;

use strict;
use warnings;

use DBI;
#use Digest::MD5 qw(md5 md5_hex md5_base64);
#use DateTime;

use lib qw(Core);
use lib qw(Classes);

use Database;

use PDBUtils qw(%AMINOACIDS_LONG_TO_SHORT);

use Configuration;
use LocalConfiguration;

use MultimerResultsManager;

my $resultsupload_manager = undef;
my $DEBUG = 0;
#Regexp definition for parsing:

my $MODEL_NAME_FORMAT1 = "^([RHOTNSFAXLnsfaxl]\\d{4}[a-zA-Z\\-]{0,3}o{0,1})([A-Z]{2})(\\d{3})_(\\d{1})(o{0,1})"; # regexp does contain info regarding the target
my $MODEL_NAME_FORMAT2 = "^([A-Z]{2})(\\d{3})_(\\d{1})(o{0,1})"; # regexp doesn't contain info regarding the target - just model
my $TARGET_NAME_FORMAT1 = "^([RHOTNSFAXLnsfaxl]\\d{4}[a-zA-Z\\-]{0,3}o{0,1})"; # oligomeric complexes of targets
#my $TARGET_NAME_FORMAT2 = "^([HOT]\\d{4}o{0,1})"; # oligomeric targets

sub new {
    my ($class) = @_;
    return $resultsupload_manager if(defined($resultsupload_manager));
    my $self = {
        _id => undef,
        _database => Database->new($CONFIG->{HOSTNAME}, $CONFIG->{PORT}, $CONFIG->{DATABASE}, $CONFIG->{USERNAME}, $CONFIG->{PASSWORD})
    };
    $resultsupload_manager = bless $self, $class;
    return $resultsupload_manager;
}

# model name parser from line record
sub parse_model_name{
    my ($self, $line, %model) = @_; 
    # the line contains info regarding the target
    if ($line =~ m/$MODEL_NAME_FORMAT1/ ){
	$model{target} = $1.$5;
	$model{pfrmat} = $2;
	$model{gr_code} = $3;
	$model{model} = $4;
    } elsif ($line =~ m/$MODEL_NAME_FORMAT2/) {
	$model{target} = undef;
        $model{pfrmat} = $1;
        $model{gr_code} = $2;
        $model{model} = $3;
    }
    return %model;
}

# target name parser from file name 
sub parse_target_name{
    my ($self, $filename, %model) = @_;
    if ($filename =~ /$TARGET_NAME_FORMAT1/) {
	$model{target} = $1;
#    } elsif ($filename =~ /$TARGET_NAME_FORMAT2/) {
#	$model{target} = $1;
    }
    return %model;
}

# load AssemblyAlignment.jar results
sub load_AssemblyAlignment {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my %model = $manager->get_new_model();
    my $infile = sprintf("%s/%s", $dir, $file);
    if (open(IN, $infile)){
	my $l = <IN>; # skip header
	while($l = <IN>){
		#Query   Target  Relation        ChainLength             RMSD    ResidueLength   [Aligned-Query] [Aligned-Target]        [Query-Target:OrientationAngle]
		# fix format - remove extra spaces
		$l =~ s/\s+\]/\]/g; 
		$l =~ s/\[\s+/\[/g; 
		$l =~ s/,\s+/,/g; $l =~ s/\s+,/,/g;
		my @tokens = split(/\s+/, $l);
		my $model_name = $tokens[0];
		%model = $self->parse_model_name($model_name, %model);
		if (! defined $model{target}){
		   my $target_name = $tokens[1];
		   %model = $self->parse_target_name($target_name, %model);
		}
		my $align_size = $tokens[3];
		my $local_rmsd =  $tokens[4];
		my $align_length = $tokens[5];
		my $txt_orient = $tokens[8]; 
		$txt_orient =~ s/\]//g; $txt_orient =~ s/\[//; # remove extra square brakets
		my $orient = undef;
		# A-A:0.03 C-C:0.02
		my $firstFlag = 1;
		foreach my $el ( split(/\s+/, $txt_orient) ) {
			if ( $el =~ m/\S+:([0-9]+\.[0-9]+)/ ) {
				my $tmp_orient = $1;
				if ($firstFlag == 1 || $orient < $tmp_orient){
					$orient = $tmp_orient;
					$firstFlag = 0;
				}
			}
		}
		$model{align_size} = $align_size;
		$model{local_rmsd} = $local_rmsd;
		$model{align_length} = $align_length;
		$model{orient} = $orient;
		# upload to database
		my $id = $manager->exist_by_parameters(%model);
	        if (!defined($id) || $id eq '' || $id == 0){
        	        $manager->add_results(%model);
	        } else {
			$model{id} = $id;
	                $manager->update_results(%model);
	        }
	last if $DEBUG; 
	}	
        close IN;
    } else {
	print "Failed to open file $infile\n";
    }
}

# load AssemblyProperties.jar results
sub load_AssemblyProperties {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my %model = $manager->get_new_model();
    my $infile = sprintf("%s/%s", $dir, $file);
    if (open(IN, $infile)){
        my $l = <IN>; # skip header
        while($l = <IN>){
		#Name    Size    Subunits        Stoichiometry   Pseudostoichiometry     Symmetry        Local   Method  SymmRMSD        SymmTMscore
                # fix format - remove extra spaces
                $l =~ s/\s+\]/\]/g; $l =~ s/\[\s+/\[/g;
		$l =~ s/,\s+/,/g; $l =~ s/\s+,/,/g;
                my @tokens = split(/\s+/, $l);
                my $model_name = $tokens[0];
                %model = $self->parse_model_name($model_name, %model);
                if ( ! defined $model{target} ) {
                   %model = $self->parse_target_name($file, %model);
                }
#		my $mm_size = $tokens[2] =~ tr/,//; # count separators (comma)
#		$mm_size = $mm_size + 1; 
#                my $stoich =  $tokens[3];
                my $symm = $tokens[5];
		my $symm_size = $tokens[1];
                my $symm_rmsd = $tokens[8];
#                $model{mm_size} = $mm_size;
#                $model{stoich} = $stoich;
                $model{symm} = $symm;
		$model{symm_size} = $symm_size;
                $model{symm_rmsd} = $symm_rmsd;
                # upload to database
                my $id = $manager->exist_by_parameters(%model);
                if (!defined($id) || $id eq '' || $id == 0){
                        $manager->add_results(%model);
                } else {
			$model{id} = $id;
                        $manager->update_results(%model);
                }
        }
        close IN;
    } else {
        print "Failed to open file $infile\n";
    }
}

# load data from model
sub load_OligoModels {
    my ($self, $file, $dir) = @_; 
    my $manager = MultimerResultsManager->new();
    my %model = $manager->get_new_model();
    $dir =~ s/\/+$//; 
    my $sub_dir = undef; my $parent_dir = undef;
    if ($dir =~ /^(.*\/)(\S+)$/){
	$parent_dir = $1; $sub_dir = $2;
    }
    if ($sub_dir !~ m//){ # homooligomeric
        my $mm_size = $self->parse_OligoSingleModel($file, $dir);
	my $stoich = 'A'.$mm_size;
	$model{mm_size} = $mm_size;
	$model{stoich} = $stoich;
	%model = $self->parse_model_name($file, %model);
	my $id = $manager->exist_by_parameters(%model);
	if ( !defined($id) || $id eq '' || $id == 0 ) {
         	$manager->add_results(%model);
        } else {
		$model{id} = $id;
	        $manager->update_results(%model);     
	}
    } else { # heterooligomeric
	
	my @sub_dirs = split(/-/, $sub_dir);
	my $mm_size = 0 ;
	my $stoich = '';
	my @letters = qw/A B C D E F G H I J K L M N O P Q R S T U V W X Y Z/;
	my $index = 0;
	
	foreach my $sd (@sub_dirs){
	  my $f = $sd; $f =~ s/o$//;
	  $f = $f.$file;
	  print $f."\n" if $DEBUG;
	  my $tmp_size = $self->parse_OligoSingleModel($f, "$parent_dir/$sd");
	  if (defined($tmp_size) && $tmp_size > 0) {
	    $mm_size += $tmp_size ;
	    $stoich .= $letters[$index].$tmp_size ;
	  }
	  $index++;
	}
	$model{mm_size} = $mm_size;
        $model{stoich} = $stoich;
	print "$sub_dir\n" if $DEBUG;
        %model = $self->parse_model_name($file, %model);
	%model = $self->parse_target_name($sub_dir, %model);
        my $id = $manager->exist_by_parameters(%model);
        if ( !defined($id) || $id eq '' || $id == 0 ) {
                $manager->add_results(%model);
        } else {
		$model{id} = $id;
                $manager->update_results(%model);     
        }

    }
}

sub parse_OligoSingleModel {
    my ($self, $file, $dir) = @_;
    my $infile = sprintf("%s/%s", $dir, $file);
    if (! -f $infile){
	$infile =~ s/o$//;
	$infile =~ s/o\//\//g;
    }
    if (! -f $infile){ 
	return undef;
    }
    if (open IN, "grep \"ATOM\" $infile | cut -c22 | sort -u | ") {
        my $mm_size = 0;
	while(my $l = <IN>){
           $mm_size += 1;
        }
	close IN;
	return $mm_size;
    } else {
	print "Failed to open file $infile\n";
	return undef;
    }
}

sub load_Stoichiometry{
    my ($self, $file, $dir) = @_;
    my $infile = sprintf("%s/%s", $dir, $file); # model file
    my $manager = MultimerResultsManager->new();
    my %model = $manager->get_new_model();
    %model = $self->parse_model_name($file, %model);
    if ( ! defined $model{target} ) {
	%model = $self->parse_target_name($file, %model);
    }
    my %hash_seqs;
    my @letters = qw/A B C D E F G H I J K L M N O P Q R S T U V W X Y Z/;
    my $letter;
    # read sequence file
    my $seq_file = sprintf("%s/templates/%s.seq.txt", $LOCAL_CONFIG->{TARGETS_DIR}, $model{target});
    if (! -f $seq_file ){
	$seq_file =~ s/o\.seq\.txt/\.seq\.txt/;
	if (! -f $seq_file ){
		return;
	}
    }
    if (open SF, "< $seq_file") {
      while(defined( my $l = <SF>)) {	
	if ($l =~ m/^>/) {
		$letter = shift @letters;
		$hash_seqs{$letter} = '';
		next;
	}
	if ($l =~ m/^[A-Z]+$/) {
		$l =~ s/\s//g;
		$hash_seqs{$letter} .= $l;
	}
      }
      close SF;
    }
    # read model pdb file
    my %mapping;
    my %hash_chains;
    open F, "grep 'ATOM' $infile | grep 'CA' | "; 
    while(defined(my $l =<F>)){
	my $chain = substr($l, 20, 2); # position 22 and reserved position 21
	$chain =~ s/\s//g;
	my $res = substr($l, 22, 4); # positions 23-26
	$res =~ s/\s//g;
	my $aa = substr($l, 17, 3); # positions 18-20
	$aa =~ s/\s//g;
	$hash_chains{$chain}{$res} = $AMINOACIDS_LONG_TO_SHORT{$aa};
	foreach my $letter (sort keys %hash_seqs) {
		if (!exists $mapping{$chain}{$letter}) {
			$mapping{$chain}{$letter} = 1;
		}
		if (length($hash_seqs{$letter}) < $res || substr($hash_seqs{$letter}, $res-1, 1) ne $hash_chains{$chain}{$res}) {
			$mapping{$chain}{$letter} = 0;
		}
	}
    }
    close F;
    my $stoich = '';
    my $mm_size = 0;
    foreach my $letter (sort keys %hash_seqs) {
	my $count = 0;
	foreach my $ch (sort keys %hash_chains) {
		if ($mapping{$ch}{$letter} == 1) {
			$count++;
		}
	}
	$mm_size += $count;
	$stoich .= "$letter".$count;
    }
    # upload do database
    $model{mm_size} = $mm_size;
    $model{stoich} = $stoich;
    my $id = $manager->exist_by_parameters(%model);
    if (!defined($id) || $id eq '' || $id == 0){
         $manager->add_results(%model);
    } else {
         $model{id} = $id;
         $manager->update_results(%model);
    }

}

sub load_QSscore {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my $infile = sprintf("%s/%s", $dir, $file);
    my $parser = "/local/Projects/Perl/casp13/src/scripts/evaluation_scripts/parseQSjson.py";
    if (open(IN, "python $parser $infile | ")){
      my %model = $manager->get_new_model();
      my $chain = undef;
      my %hash_chains; my %mapping;
      while(defined(my $l = <IN>)){
	if ($l =~ m/^model:\s*(\S+)/){
	   my $model_name = $1;
	   %model = $self->parse_model_name($model_name, %model);
	}
	#model: H0953TS068_1
	if ($l =~ m/^reference:\s*(\S+)/){
	   my $target = $1;
	   %model = $self->parse_target_name($target, %model);
	}
	#reference: H0953.pdb
	if ($l =~ m/^qs_glob:\s*(\S+)/){
	   $model{qs_glob} = $1;
	}
	#qs_glob:  0.0959630204741
        if ($l =~ m/^qs_best:\s*(\S+)/){
           $model{qs_best} = $1;
        }
	#qs_best:  0.0960988516622
	if ($l =~ m/^qs_best:\s*(\S+)/){
           $model{qs_best} = $1;
        }
	#rmsd:  23.3679218292
	if ($l =~ m/^rmsd:\s*(\S+)/){
           $model{global_rmsd} = $1;
        }
	#oligo_lddt:  0.231164142304
	if ($l =~ m/^oligo_lddt:\s*(\S+)/){
           $model{oligo_lddt} = $1;
        }
	#w_lddt:  0.289507876076
	if ($l =~ m/^w_lddt:\s*(\S+)/){
           $model{w_lddt} = $1;
        }
	#chain_map:  A:C,C:D,B:B,D:A,
	if ($l =~ m/^chain_map:\s*(\S+)/){
	   my $ch_map = $1; $ch_map =~ s/,$//;
           $model{chain_map} = $ch_map;
	   my @tokens = split(/,/, $ch_map);
	   foreach my $t (@tokens) {
		if ($t =~ m/(\S+):(\S+)/) {
			my $ch_t = $1; my $ch_m = $2;
			$mapping{$ch_m} = $ch_t;
		}
	   }
        }
	#chain C:0.299536019564
	if ($l =~ m/^chain\s+(\S+):(\S+)/){
	   $chain = $1; my $lddt = $2;	
	   if (!exists $hash_chains{$chain}) {
		$hash_chains{$chain} = {
			_chain_m => $chain,
			_chain_t => $mapping{$chain},
			_lddt => $lddt,
			_per_res => ''
		}
	   }
	}
	if (defined($chain)) {
	  #C:5:0.242388755083
	   if ($l =~ m/^$chain:(\d+):([0-9]+\.{0,1}[0-9]+)/) {
		my $res = $1; my $score=$2;
		if ($hash_chains{$chain}->{_per_res} ne ''){
			$hash_chains{$chain}->{_per_res} .= ',';
		}
		$hash_chains{$chain}->{_per_res} .= sprintf("%d:%.4f", $res, $score);
	   }
	}
      }
      my $id = $manager->exist_by_parameters(%model);
      if (!defined($id) || $id eq '' || $id == 0){
           $manager->add_results(%model);
      } else {
           $model{id} = $id;
           $manager->update_results(%model);
      }
      # score per residue
      foreach my $chain (keys %hash_chains){
	my $id_per_res =  $manager->exist_record_per_res($id, $hash_chains{$chain}->{_chain_m});
	if (defined($id_per_res) && $id_per_res > 0){
		$manager->update_record_per_res($id_per_res, $id, $hash_chains{$chain}->{_chain_m}, $hash_chains{$chain}->{_chain_t}, $hash_chains{$chain}->{_lddt}, $hash_chains{$chain}->{_per_res});
	} else {
		$manager->add_record_per_res($id, $hash_chains{$chain}->{_chain_m}, $hash_chains{$chain}->{_chain_t}, $hash_chains{$chain}->{_lddt}, $hash_chains{$chain}->{_per_res});
	}
      }
    } else {
        print "Failed to process file $infile\n";
    }

}

=head
# load QSscore results
sub load_QSscore {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my $infile = sprintf("%s/%s", $dir, $file);
    if (open(IN, $infile)){
	my %model = $manager->get_new_model();
	%model = $self->parse_model_name($file, %model);
	if (!defined $model{target} || $model{target} eq ''){
		%model = $self->parse_target_name($file, %model);
	}
	my $qs_flag = 0;
	my $oligo_lddt_flag = 0;
	my $w_lddt_flag = 0;
	my $ch_map_flag = 0; my $ch_map = '';
	my $single_chain_lddt_flag = 0;
        while(my $l = <IN>){
		if ($l =~ m/"chain_mapping"/ ) {
			$ch_map_flag++;
			$w_lddt_flag = 0;
                        $oligo_lddt_flag = 0;
			$qs_flag = 0;
			next;
		}
		if ($l =~ m/"oligo_lddt"/) {
			$oligo_lddt_flag++;
			$w_lddt_flag = 0;
                        $ch_map_flag = 0;
			$qs_flag = 0;
			next;
		}
		if ($l =~ m/"weighted_lddt"/) { 
                        $w_lddt_flag++;
                        $ch_map_flag = 0;
                        $oligo_lddt_flag = 0;
			$qs_flag = 0;
			next;
                }
		if ($l =~ m/"single_chain_lddt"/){
			$w_lddt_flag = 0;
                        $ch_map_flag = 0;
                        $oligo_lddt_flag = 0;
			$qs_flag = 0;
			next;
		}
		if ($l =~ m/"qs_score"/) {
                        $w_lddt_flag = 0;
                        $ch_map_flag = 0;
                        $oligo_lddt_flag = 0;
                        $qs_flag++ ;
                }
		if ($ch_map_flag>0) {
			if ($l =~ m/"(\S+)":\s+"(\S+)"/,) {
				$ch_map .= "$1:$2,";
				next;
			}
		}
		if ($l =~ m/"global_score"/) {
			if ($oligo_lddt_flag > 0){
				if ($l =~ m/"global_score":\s+([0-9\.]+),/){
					$model{oligo_lddt} = $1;
					$oligo_lddt_flag = 0;
				}
			} elsif ($w_lddt_flag > 0){
                                if ($l =~ m/"global_score":\s+([0-9\.]+),/){
                                        $model{w_lddt} = $1;
                                        $w_lddt_flag = 0;
                                }
                        } elsif ($qs_flag > 0){
                                if ($l =~ m/"global_score":\s+([0-9\.]+),/){
                                        $model{qs_glob} = $1;
                                } 
                        }
		} elsif ($l =~ m/"best_score"/) {
			if ($qs_flag > 0){
				if ($l =~ m/"best_score":\s+([0-9\.]+),/){
					$model{qs_best} = $1;
				}
			}
			$qs_flag = 0;
		}
        }
        close IN;
	$ch_map =~ s/,$//;
	$model{chain_map} = $ch_map;
	my $id = $manager->exist_by_parameters(%model);
        if (!defined($id) || $id eq '' || $id == 0){
                $manager->add_results(%model);
        } else {
                $model{id} = $id;
                $manager->update_results(%model);
        }
    } else {
        print "Failed to open file $infile\n";
    }
}
=cut

# load cont_clash results
sub load_cont_clash {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my $infile = sprintf("%s/%s", $dir, $file);
    if (open(IN, $infile)){
        my $l = <IN>; # skip header
	while($l = <IN>){
		unless ($l =~ m/\s+ALL\s+/){
                        next;
                }
                my %model = $manager->get_new_model();
		my @tokens = split(/\s+/, $l);
		%model = $self->parse_model_name($tokens[0], %model);
		if (! defined $model{target}) {
			%model = $self->parse_target_name($file, %model);
		}
		my $no_conts = $tokens[2];
		my $no_clashes = $tokens[3];
		$model{no_conts} = $no_conts;
		$model{no_clashes} = $no_clashes;

		my $id = $manager->exist_by_parameters(%model);
                if (!defined($id) || $id eq '' || $id == 0){
                        $manager->add_results(%model);
                } else {
			$model{id} = $id;
                        $manager->update_results(%model);
                }
	}
    } else {
	print "Failed to open file $infile\n";
    }
}

# load dens_corr results
sub load_dens_corr {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my $infile = sprintf("%s/%s", $dir, $file);
    if (open(IN, $infile)){
        my $score = <IN>;  $score =~ s/\s//g;
	my %model = $manager->get_new_model();
	%model = $self->parse_model_name($file, %model);
	$model{dens_corr} = $score;
	my $id = $manager->exist_by_parameters(%model);
        if (!defined($id) || $id eq '' || $id == 0){
                #$manager->add_results(%model);
        } else {
                $model{id} = $id;
                $manager->update_results(%model);
        }
    } else {
        print "Failed to open file $infile\n";
    }
}

# load TM_score results
sub load_tm_multi {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my $infile = sprintf("%s/%s", $dir, $file);
    if (open(IN, $infile)){
        my $l = <IN>; # skip header
	$l = <IN>;
	my ($tm, $gdt) = split(/,/, $l);
        my %model = $manager->get_new_model();
        %model = $self->parse_model_name($file, %model);
        $model{tm_score} = $tm;
	$model{gdt_ts} = $gdt;
        my $id = $manager->exist_by_parameters(%model);
        if (!defined($id) || $id eq '' || $id == 0){
                #$manager->add_results(%model);
        } else {
                $model{id} = $id;
                $manager->update_results(%model);
        }
    } else {
        print "Failed to open file $infile\n";
    }
}


# load ananas results
sub load_ananas {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my $infile = sprintf("%s/%s", $dir, $file);
    if (open(IN, $infile)){
        my $l = <IN>; # skip header
        while($l = <IN>){
                #unless ($l =~ m//){
                #        next;
                #}
		if ($l =~ m/^(\S+)\s+;\s+(.+)$/) {
		my $model_name = $1;
		my $symm_rmsd = $2;
		# find the optimal group - with min rmsd
		my @tokens = split(/\s+/, $symm_rmsd);
		my $min_rmsd; my $min_symmgr_rmsd = '';
		my $i = 0;
		while($i < scalar(@tokens)){
		  if ($tokens[$i] =~ m/\S+:(\S+)/){
		    my $rmsd = $1; $rmsd =~ s/;//;
		      if ($i == 0 || $min_rmsd > $rmsd){
		 	$min_rmsd = $rmsd;
                        $min_symmgr_rmsd = $tokens[$i];
		      } 
		  }
		  $i++;
		}

                my %model = $manager->get_new_model();
                #my @tokens = split(/\s+/, $l);
                %model = $self->parse_model_name($model_name, %model);
                if (! defined $model{target}) {
                        %model = $self->parse_target_name($file, %model);
                }
                $model{symmgr_rmsd} = $symm_rmsd;
		$model{min_symmgr_rmsd} = $min_symmgr_rmsd;

                my $id = $manager->exist_by_parameters(%model);
                if (!defined($id) || $id eq '' || $id == 0){
#                        $manager->add_results(%model);
                } else {
                        $model{id} = $id;
                        $manager->update_results(%model);
                }
		}
        }
    } else {
        print "Failed to open file $infile\n";
    }
}


# load Interface results
sub load_Interface {
    my ($self, $file, $dir) = @_;
    my $manager = MultimerResultsManager->new();
    my $infile = sprintf("%s/%s", $dir, $file);
    my $sum_tconts = $self->parseNoContsAllInterfaces($infile);
    if (open(IN, $infile)){
        my $l = <IN>; # skip header
	my $flagFirst = 0;
	my @linesPerGroup = ();
        while($l = <IN>){
	  if ($l =~ m/^=/){
		if ($flagFirst == 1) {
		   # process a bunch of lines corresponding to the same group
		   $self->processInterfaceLinesForGroup(\@linesPerGroup, $file, $manager, $sum_tconts);
		   @linesPerGroup = ();
		}
		$flagFirst = 1;
		next;
	  }
	  if ($l =~ m/^$/){next;}
	  push @linesPerGroup, $l ; 
        }
        close IN;
	# process a bunch of lines corresponding to the last group
	$self->processInterfaceLinesForGroup(\@linesPerGroup, $file, $manager, $sum_tconts);
    } else {
        print "Failed to open file $infile\n";
    }
}

sub processInterfaceLinesForGroup{
    my ($self, $refLines, $file, $manager, $sum_tconts) = @_;
    my @lines = $self->processInterfaceLinesPerInterface($refLines);
    # my @lines = @{$refLines};
    my %model = $manager->get_new_model();
    my $firstFlag = 1;
    my @tconts = ();
    my @f1s = ();
    my @jaccards = ();
    my @precs = ();
    my @recalls = ();
    my $rmsd = undef;
    foreach my $l (@lines){
#	if ($l =~ m/QSscore\s+did\s+not\s+report/i){
#		next;
#	}
	$l =~ s/\|//g; # remove extra symbols
	my @tokens = split(/\s+/, $l);
	if ($firstFlag == 1){
		$firstFlag = 0;
		%model = $self->parse_model_name($tokens[0], %model);
		if (! defined $model{target}){
		   %model = $self->parse_target_name($file, %model);
		}
		$rmsd = $tokens[10];
	}
	push @tconts, $tokens[2];
	push @f1s, $tokens[7];
	push @jaccards, $tokens[11];
	push @precs, $tokens[5];
	push @recalls, $tokens[6];
	if ($rmsd > $tokens[10]){
	    $rmsd = $tokens[10];
	}
    }
    my $f1 = 0.0; my $jaccard = 0;  my $prec = 0; my $recall = 0; #my $sum_tconts = 0;
    for (my $i = 0; $i < scalar(@tconts); $i++){
	$f1 += $tconts[$i]*$f1s[$i];
	#$jaccard += $tconts[$i]*(1 - $jaccards[$i]); CASP12
	$jaccard += $tconts[$i]*$jaccards[$i];
	$prec += $tconts[$i]*$precs[$i];
	$recall += $tconts[$i]*$recalls[$i];
	#$sum_tconts += $tconts[$i];
    }
    #$f1 = $f1*scalar(@tconts)/$sum_tconts;
    $f1 = $f1/$sum_tconts;
    #$jaccard = $jaccard*scalar(@tconts)/$sum_tconts;
    #$jaccard = 1 - $jaccard/$sum_tconts; CASP12
    $jaccard = $jaccard/$sum_tconts;
    $prec = $prec/$sum_tconts;
    $recall = $recall/$sum_tconts;
    $model{f1} = $f1;
    $model{jaccard_d} = $jaccard;
    $model{iface_rmsd} = $rmsd;
    $model{prec_iface} = $prec;
    $model{recall_iface} = $recall;
    my $id = $manager->exist_by_parameters(%model);
    if (!defined($id) || $id eq '' || $id == 0){
        $manager->add_results(%model);
    } else {
	$model{id} = $id;
        $manager->update_results(%model);
    }
}

sub processInterfaceLinesPerInterface{
    my ($self, $refLines) = @_;
    my @result;
    my @lines = @{$refLines};
    my @arr = ();
    my $index = 0;
    foreach my $l (@lines){
        $l =~ s/\|//g;
        my @tokens = split(/\s+/, $l);
        my $t_interface = $tokens[1];
        $t_interface =~ s/:\S+//;
        my $f1 = $tokens[7];
        my $jaccard_d = $tokens[11];
        push @arr, {
          index => $index++,
          t_interface => $t_interface,
          f1 => $f1,
          jaccard => $jaccard_d
        };
    }
    @arr = sort {$b->{jaccard}<=>$a->{jaccard}} @arr; # sort by jaccard coefficient in descending order
    @arr = sort {$b->{f1}<=>$a->{f1}} @arr; # sort by jaccard distance in descending order
    my %done;
    foreach my $el (@arr){
        if (exists $done{$el->{t_interface}}){
                next;
        } else {
                $done{$el->{t_interface}} = 1;
        }
        push @result, $lines[$el->{index}];
    }
    return @result;
}

sub parseNoContsAllInterfaces{
    my ($self, $infile) = @_;
    if (open I, "<$infile"){
	    my %hash;
	    while(defined(my $l = <I>)){
		# T0889TS005_1o   T_AB:M_AB    124    83    20  80.6  66.9  73.1 |    86 100.00   1.84 0.19
	        if ($l =~ m/^\S+\s+(T_[A-Za-z]{2}):\S+\s+(\d+)/){
			my $t_iface = $1; my $no_conts = $2;
			$hash{$t_iface} = $no_conts;
		}
	    }
	    close I;
	    my $result = 0;
	    foreach my $k (keys %hash){
		$result += $hash{$k};
	    }
	return $result;
    } else {
	print "Failed to open file $infile\n";
	return undef;
    }
}

1;
