#!/usr/bin/perl -w
use strict;

#person in charge of this script
#this should be the person currently in charge of scripts for the SGN project
my $script_maintainer='Teri Solow <tms45@cornell.edu>';

# 0 for normal operation
my $debug = 0;

#local packages to use
use runtime;
use db_link;
use projects;
use Data::Dumper;

@ARGV or print "No input parameters, proceeding with default.\n";

my @arg_pairs = split (/(^|\W)\-/, (join ' ', @ARGV));

my %args=();

foreach (@arg_pairs){
	$_ or next;
	my ($flag, $val)=split /\s+/;
	$flag or next;
	$args{$flag}=$val;
}
my $project=$args{'p'};
my $indir=$args{'i'};
my $donedir=$args{'d'};

#set defaults for io, script filename, etc
$project or die "Please specify a project (cgn, fgn, pgn) using the -p flag\n";
$indir ||= "/data/shared/pgn_data_processing/blast_annotations/${project}/02_parsed_output";
$donedir ||= "/data/shared/pgn_data_processing/blast_annotations/${project}/done";

# get db info
my ($db, $usr) = @{projects::get_db_info($project)};
$db or die "No known database for project $project";

#Main body of the script
########################
# get the list of files in $indir
opendir(FOLDER, $indir) or die "Cannot open ${indir}: $!\n";
my @files=readdir(FOLDER);
closedir(FOLDER);

# connect to the database
my $dbh = db_link::connect_db($db, $usr) or die "couldn't open database link\n";

# get hash of the blast target ids
my %targets;
my ($target_id, $target_name);
my $sth = $dbh->prepare("select blast_target_id, target_name from blast_target;") or die "Can't prepare statement: $DBI::errstr";
my $rv = $sth->execute or die "Can't execute statement: $DBI::errstr";
my $rc = $sth->bind_columns(\$target_id, \$target_name);
while ($sth->fetch){
	$targets{$target_name}=$target_id;
}
($debug>0) and print Dumper(%targets);

my $start_time=time;

# load data for each of the appropriate files in this directory
foreach my $file (@files) {
	if ( $file =~ /^unigene_build_([-a-zA-Z0-9]+)_vs_([-_A-Za-z0-9]+)\.txt$/ ) {

		# metainfo
		my $build = $1; # unigene build number
		my $target = $2; # target name (short)
		
		# delete all previous results for this organism
		if (($debug == 0) && ($build =~ /[0-9]+/)) {

			# get the organism id for this build
			my $organism_id;
			$sth = $dbh->prepare("select organism_id from unigene_build where unigene_build_id='$build';") or die "Can't prepare statement: $DBI::errstr";
			$rv = $sth->execute or die "Can't execute statement: $DBI::errstr";
			$rc = $sth->bind_columns(\$organism_id);
			$sth->fetch;

			# delete all results from the same organism against the same target
			$sth = $dbh->prepare("delete from unigene_blast_result using unigene_blast_result, unigenes, unigene_build where unigene_blast_result.unigene_id=unigenes.unigene_id and unigenes.unigene_build_id=unigene_build.unigene_build_id and unigene_build.organism_id='$organism_id' and unigene_blast_result.blast_target_id='$targets{$target}';") or die "Can't prepare statement: $DBI::errstr";
			$rv = $sth->execute or die "Can't execute statement: $DBI::errstr";
		}
		
		# open file
		open (FILEIN, "$indir/$file") or die "Could not open $indir/$file for reading: $!\n";

		# iterate through file
		while(<FILEIN>) {

			my ($unigene, $length, $description);

			# there will be one set of results per line of the parsed result
			# file
			my ($report, $subject, $evalue, $score, $identities, $sbjct, $frame) = split /\t/;

			# parse the report into its subparts
			# e.g., <unigene_id> (<length> letters)  vs. <target_name>
			# we get the target from the filename, so that can be ignored
			if ($report =~ m/^([0-9]+) +\(([0-9]+) letters\)/) {
				$unigene = $1;
				$length = $2;
			}
			$length ||= 0;

			# parse out the $subject, basically just removing he preceeding
			# '>' and sanitizing quotes
			if ($subject =~ m/^>(.*)/) {
				$subject = $1;
				$subject =~ s/['"]//g;
			}

			# trim out e-value label
			# this can have letters as well as numbers
			if ($evalue =~ m/E-value: +(.*)/) {
				$evalue = $1;
			}

			# trim out score label
			if ($score =~ m/Score: +([0-9.]+)/) {
				$score = $1;
			}

			# trim out %identities label
			if ($identities =~ m/%Identities: +([0-9.]+)/) {
				$identities = $1;
			}

			# trim out sbjct label
			if ($sbjct =~ m/Sbjct: +([0-9.]+)/) {
				$sbjct = $1;
				my ($s_start, $s_end) = split/\.\./, $sbjct;
				$s_start ||= 0;
				$s_end ||= 0;
				if (($s_start < $s_end) && ($s_start%3 == 0)) {
					$sbjct = 3;
				}
				else {
					$sbjct = -(($length-$s_start)%3)-1;
				}	
			}

			if ($debug>0) {
				print "Unigene ${unigene}:\n";
				$target_id and print "\ttarget:     \t$targets{$target}\n";
				$length and print "\tlength:     \t$length\n";
				$subject and print "\tdescription:\t$subject\n";
				$evalue and print "\tevalue:     \t$evalue\n";
				$score and print "\tscore:      \t$score\n";
				$identities and print "\t%identities:\t$identities\n";
				$sbjct and print "\tframe:      \t$sbjct\n";
			}
			
			# load these results into databse
			my $stm = "insert into unigene_blast_result (unigene_id, blast_target_id, match_description,  evalue, match_score, identity_pct, frame) values (?, ?, ?, ?, ?, ?, ?)";
			$sth = $dbh->prepare($stm) or die "Can't prepare statement: $DBI::errstr";
			if ($debug == 0) {
				$rv = $sth->execute($unigene, $targets{$target}, $subject, $evalue, $score, $identities, $sbjct) or die "Can't execute statement: $DBI::errstr";
			}

			($debug>2) and exit; # exit after one line with greater debugging
		}
		
		close FILEIN;

		# clean up these files so they won't accidentally be considered 
		# again later
		# ($debug == 0) and unlink("$indir/$file");
		($debug == 0) and `mv $indir/$file $donedir/`;
		
	}
	else {
		if ($file ne "." && $file ne "..") {
			print "Skipping $file...\n";
		}
	}
}
runtime::runtime_print($start_time, "Loading data");
db_link::disconnect_db($dbh);

