#!/usr/bin/perl
use warnings;
use strict;
#STANDARD FORMAT TOKENS:
my $PFRMAT	="^PFRMAT";
my $TARGET	="^TARGET";
my $AUTHOR	="^AUTHOR";
my $MODEL 	="^MODEL";
my $METHOD 	="^METHOD";
my $SCORE	="^SCORE";
my $REMARK	="^REMARK";
my $END		="^END";
my $HEADER_END	="^\$";
my $NUMBER_IN_FIRST_COLL="^[0-9]";
my $PARENT	="^PARENT";

#SPECIFIC TOKENS FOR FN FORMAT
my $BindingSite		="Binding site:";
my $Comment		="Comment:";

#STATES OF THE LEXICAL ANALYZER
my $m_section=0; #1 - if in MODEL section

#OBLIGATORY FIELDS COUNTERS
my %fields_count=(
 $PFRMAT => 0,
 $AUTHOR => 0,
 $TARGET => 0,
 $METHOD => 0,
 $MODEL => 0,
 $END => 0
);
#ADDITIONAL VARIABLES

my $status=0;
my $method=0;
my $num_line=0;


while (<>){
my $error=0;
$num_line++;
chomp;
$status=0;
  SWITCH: {
	/$PFRMAT/i && (!$m_section) 	&& do {
						$status=check_pfrmat($_);	
						$fields_count{$PFRMAT}++;
						last SWITCH;
			    		};
	/$AUTHOR/i && (!$m_section) 	&& do { 
						$status=check_author($_);
						$fields_count{$AUTHOR}++;
						last SWITCH;	
			    		};
	/$TARGET/i && (!$m_section) 	&& do { $status=check_target($_);
						$fields_count{$TARGET}++;
						last SWITCH;	
			    		};
	/$MODEL/i  && (!$m_section) 	&& do { $m_section=1;
						$fields_count{$MODEL}++;	
						$status=check_oheadf(%fields_count);
						if ($status eq 0) { $status=check_model($_);}
						last SWITCH;	
			    		};
	/$METHOD/i && (!$m_section) 	&& do { $method++;
						$fields_count{$METHOD}++;
						last SWITCH;	
			    		};
	/$SCORE/i   			&& do {
						last SWITCH;	
			    		};	
	/$REMARK/i  			&& do { $status=check_remark($_);
						last SWITCH;	
			    		};
	/$END/i	   && ($m_section)  	&& do { $m_section=0;
						$fields_count{$END}++;
						last SWITCH;	
			    		};
	/$BindingSite/i   && ($m_section) && do { $status=check_bindings($_);
						$fields_count{$BindingSite}++;	
						last SWITCH;	
					};	
	/$Comment/i	 && ($m_section) && do { 
						last SWITCH;
			    		};
        /^\s*$/		 		&& do {
						last SWITCH;
			   		};
      $error=1;  
   }
 if ($status ne 0) {print "# ERROR! (Line no. $num_line): $status\n";}
 if ($error) {print "# ERROR! (Line no. $num_line): Unknown or misplaced record in the following line: $_\n";}
}

check_eof(%fields_count);


#------------------------------------
#   Subroutines for parsing tokens:
#____________________________________

sub check_pfrmat {
  my @params=@_;
  my @fields=split /\s+/, $params[0];
  my $length=scalar @fields;
  if ($length > 2){
  return "ERROR! Too many fields after PFRMAT"; 
  } elsif ($length < 2) { return "ERROR! Please specify type of prediction after PFRMAT";}
  if ($fields[1] =~ /^FN$/) {return 0;}
  else { return "ERROR! Check the type of prediction after PFRMAT - it must be FN";}
  return 0;
}


sub check_author {
 my @params=@_;
 my $param=$params[0];
 #this functionaty moved to Submission.pm 
 #if ($param =~ /$AUTHOR\s+\d{4}-\d{4}-\d{4}\s*$/i) { return 0;}
 #return "ERROR! Please check the line:  $param"; 
 return 0;
}

sub check_target {
 my @params=@_;
 my $param=$params[0];
 if ($param =~ /$TARGET\s+T[0-9]+\s*$/i) { return 0;}
 return "ERROR! Please check the line:  $param"; 
 return 0;
}

sub check_model {
 my @params=@_;
 my $param=$params[0];
 if ($param =~ /$MODEL\s*[0-9]+\s*$/i) { return 0;}
 return "ERROR! Please check the line:  $param"; return 0;
}

sub check_remark {
 return 0;
}

sub check_bindings {
 my @params=@_;
 my $param=$params[0];
 (my @fields)=split (/:/, $param) ;
 if ($#fields > 1){
   return "ERROR! Too many colons in the line:  $param";
 }
 if ($fields[1]) {
  my @records=split (/;/, $fields[1]);
  foreach my $record (@records) {
   if ($record !~ /^\s*[A-Z]?\d+\s*((,|-){1}\s*[A-Z]?\d+\s*,?)*$/){
     return "ERROR! Please check the line:  $param";
   }
  }
 }
 return 0;
}

sub check_rr {
 return 0;
}

sub check_oheadf {
 my %fields_max_count=(
  $PFRMAT => 1,
  $AUTHOR => 1,
  $TARGET => 1,
  $METHOD => 20000000, #some large number 
  $MODEL => 1,
  $END => 1,
  $BindingSite => 1,
 );
 my %fields_min_count=(
  $PFRMAT => 1,
  $AUTHOR => 1,
  $TARGET => 1,
  $METHOD => 1,
  $MODEL => 1,
  $END => 0, 
  $BindingSite => 0,
 );
 my %params=@_;
 my $item;
 for  (keys %params) {
   if ($fields_max_count{$_} < $params{$_})
    {return "ERROR!: Too many $_ records in a prediction!";}
   elsif ($fields_min_count{$_} > $params{$_}) { return "ERROR! Record  $_ is missing - must be at least $fields_min_count{$_} present!";} 
 } 
 return 0;
}

sub check_eof {
 my %fields_max_count=(
  $PFRMAT => 1,
  $AUTHOR => 1,
  $TARGET => 1,
  $METHOD => 20000000, #some large number
  $MODEL => 1,
  $END => 1,
  $BindingSite => 10,
 );
 my %fields_min_count=(
  $PFRMAT => 1,
  $AUTHOR => 1,
  $TARGET => 1,
  $METHOD => 1,
  $MODEL => 1,
  $END => 1,
  $BindingSite => 0,
 );
 my %params=@_;
 my $item;
 for  (keys %params) {
   if ($fields_max_count{$_} < $params{$_})
    {print "# ERROR! Too many $_ records in a prediction!";}
   elsif ($fields_min_count{$_} > $params{$_}) {print "# ERROR! Record $_ is missing - must be at least $fields_min_count{$_} present!";}
 }
 return 0;
}

