#!/usr/bin/perl

# require '/genome/web/cgi-bin/HS/config.pl';

use Bio::Seq;
use Bio::SeqIO;
use Bio::SeqFeature::Generic;
use Bio::SeqIO::genbank;
use DBI;
use DBD::mysql;

use strict;
use warnings;

our $DB_HOST;
our $DB_USER;
our $DB_PASS;
require '/genome/web/cgi-bin/HS/config.pl';

my $usage = "getGBinfo.pl <infile> <dbname> <outdir>";
my $infile = shift or die $usage;
my $dbName = shift or die $usage;
my $outDir = shift or die $usage;

my $dbh = DBI->connect("DBI:mysql:$dbName:$DB_HOST",$DB_USER,$DB_PASS,{RaiseError => 1});

my $seq_in = Bio::SeqIO->new('-file' => "<$infile",
			     '-format' => 'GenBank');


my %contig;
($contig{'id'}) = ($infile =~ /contig(\d+)|ctg(\d+)/i); ## ignore case
if ($contig{'id'} !~ /\d+/){
	print "Impossible to determine contig number in file $infile. Skipping this file.";
	exit (1);
}
# print "Adding Contig #".$contig{'id'}."<BR>";

my %validCodes;
my $seq = $seq_in->next_seq();
my $contigSeq = $seq->seq();
our $show=0;
%validCodes = getValidCodes($dbh);

my $featGENE = 0;
my $featCDS = 0;

for my $feat_object ($seq->get_SeqFeatures) {
	$show=0;
	my %infoORFs;
	my %annot;
# 	if (($feat_object->primary_tag =~ /^gene$/) && !$featCDS){
# 		$featGENE = 1;
# 	}elsif (($feat_object->primary_tag =~ /^CDS$/) && !$featGENE){
# 		$featCDS = 1;
# 	}

	if (
# 	    (($feat_object->primary_tag =~ /^gene$/) && !$featCDS )
# 	    ||
	    (($feat_object->primary_tag =~ /^CDS$/)  && !$featGENE)
	   ){

		$infoORFs{'start'} = $feat_object->start;
		$infoORFs{'end'} = $feat_object->end;

		my $strand = $feat_object->strand;

		my $id;
		if ($feat_object->has_tag('locus_tag')){
			($id) = $feat_object->get_tag_values('locus_tag');
		}elsif ($feat_object->has_tag('gene')){
			($id) = $feat_object->get_tag_values('gene');
		}elsif ($feat_object->has_tag('gene_id')){
			($id) = $feat_object->get_tag_values('gene_id');
# 			print $id."\n";
		}
		($annot{'orf_name'}) = $feat_object->get_tag_values('gene');
# 		else{
# 			print "Impossible to determine gene id in file $infile.<BR>\n";
# 			for my $tag ($feat_object->get_all_tags) {             
# 				print "  tag: ", $tag, "-";             
# 				for my $value ($feat_object->get_tag_values($tag)) {                
# 					print "    value: ", $value, "<BR>";             
# 				}          
# 			}
# 			next;
# 		}

# 		print "id: ".$id."start: ".$infoORFs{'start'}."end: ".$infoORFs{'end'}."<BR>";

		$infoORFs{'contig_num'} = $contig{'id'};
		($infoORFs{'id'}) = ($id =~ /(\d{3}\.\d{4}.*)$/);
		($infoORFs{'frame'}) = getFrame($infoORFs{'start'},$infoORFs{'end'}, $strand);

		$annot{'id'} = $infoORFs{'id'};
		$annot{'contig_num'} = $contig{'id'};

		my $valid;
		my $fs;
		my $note;
		if ($feat_object->has_tag('note')){
			($note) = $feat_object->get_tag_values('note');

			($valid) = ($note =~ /VALIDATION:(\w+\s?\w+)\|/);
			if ($valid){
				$valid = lc $valid;
				$annot{'validation'} = $validCodes{$valid};
			}
	
			($fs) = ($note =~ /FRAMESHIFT:(\w{2,3})\|/);
			$annot{'frameshift'} = '';
			if ($fs && $fs =~ /yes/){
				$annot{'frameshift'} = 1;
			}
		}

		if ($feat_object->has_tag('product')){
			($annot{'product'}) = $feat_object->get_tag_values('product');
		}
		if ($feat_object->has_tag('function')){
			($annot{'function'}) = $feat_object->get_tag_values('function');
		}

		insert($dbh,  'infoORF', %infoORFs);
		insert($dbh,  'annot', %annot);

		my $orfSeq = substr($contigSeq, $infoORFs{'start'} - 1, ($infoORFs{'end'} - $infoORFs{'start'})+1);
		writeSeq($outDir, "ORF".$infoORFs{'id'}, $orfSeq);

	}elsif ($feat_object->primary_tag =~ /^source$/){
		$contig{'length'} = $feat_object->length;
	}
}
insert($dbh,  'contigs', %contig);

######################
#### SUB ROUTINES ####
######################

sub getValidCodes{
	my ($dbh) = @_;

	my $q = "SELECT * FROM annotV1.validation";
	my $res = $dbh->prepare($q);
	$res->execute();
	my %validation;

	while (my $data = $res->fetchrow_hashref()) {
		my %data = %{$data};
		my $status = lc $data{'status'};
		$validation{$status} = $data{'val_cod'};
	}

	return %validation;
}

sub getFrame{
	my ($start, $end, $strand) = @_;

	my $frame;
	if ($strand == 1){
		$frame = $start % 3;
		if ($frame == 0){
			$frame = 3;
		}
		$frame = "F".$frame;
	}else{
		$frame = $start % 3;
		if ($frame == 2){
			$frame = 3;
		}elsif ($frame == 0){
			$frame = 2;
		}
		$frame = "R$frame";
	}

	return $frame;
}

sub insert{
	my ($dbh, $tableName, %data) = @_;

	my @table;my @value;my $q;my $tbl;my $vle;

	for my $k (keys %data){
		push @table, $k;
		push @value, $data{$k};
	}

	$q = "INSERT INTO $tableName ";
	$tbl = "(";
	$vle = " VALUES (";

	for (my $i=0; $i<@table; $i++){
		$tbl .= $table[$i].", ";
		$vle .= "\"".$value[$i]."\", ";
	}

	$tbl =~ s/,\s$/)/;
	$vle =~ s/,\s$/)/;

	$q .= $tbl.$vle;

# 	if ($show){
# 		print $q."<BR>";
# 	}
	$dbh->do($q);
}

sub writeSeq{
	my ($orfDir, $header, $seq) = @_;

	my $aaDir = $orfDir."/n";
	my $ptDir = $orfDir."/p";
# print "--".$aaDir."<BR>"."++".$ptDir."<BR>";

	my $aaFile = $aaDir.'/'.$header;
	my $ptFile = $ptDir.'/'.$header;

	open(AAORF, ">$aaFile");
	open(PTORF, ">$ptFile");

	print AAORF ">$header".".n\n";
	print AAORF $seq;

	my $in = Bio::PrimarySeq->new ('-seq' => $seq);
	my $proteinSeq = $in->translate();
	print PTORF ">$header".".p\n";
	print PTORF $proteinSeq->seq."\n";

	close(AAORF);
	close(PTORF);
}