package GO::GOBlast;
use DictyBaseConfig;
use Blast::Client_Config;
use Blast::Client_View;
use GO::GOGeneBlastInfo;
use GO::GOGeneAssociationParser;
use Data::Dumper;
use Net::SFTPW32;
use Login;
use Feature;
use Feature;
use dicty::Dbtable::Display_seq;
use dicty::Feature;
use strict;

sub new
{
    my ($type, $dbh) = @_;
    my $self = {};
    $self->{'dbh'} = $dbh;
    $self->{'feature'} = undef;
    $self->{'blastconfig'} = undef;
    bless $self, $type;
   $self->_initBlast();
    return $self;
}
sub feature
{
    my $obj = shift;
    @_ ? $obj->{feature} = shift
       : $obj->{feature};
}

sub blastconfig
{
    my $obj = shift;
    @_ ? $obj->{blastconfig} = shift
       : $obj->{blastconfig};
}

sub getSequence
{
    my ($self, $featno) = @_;
    my $dbh  = $self->{'dbh'};
    ;
    my $feature  = new dicty::Feature(-feature_no =>  $featno);
    $self->{'feature'} = $feature;
    my $sequence = $feature->sequence(-TYPE => "Protein");
    return $sequence;

}


sub _initBlast
{
  my $self = shift;
  $| = 1;
#
# conatains blastall options and client options configuration
#
my $blastConfig = new Blast::Client_Config();
#my $blast_host = '165.124.55.143';
my $blast_host = $ENV{'XSERVER'};
my $blast_server = SOAP::Lite
       -> ns('http://dictyBase.org/Blast')
       -> proxy("http://$blast_host/cgi-bin-internal/blast.pl");

$blastConfig->blast_server($blast_server);



# conatains methods that write html
#
my $blastView  = new Blast::Client_View();

#
# view uses configuration so set configuration subobject of blastView
#
$blastView->config( $blastConfig );

#
# get default options
#
my %options = %{ $blastConfig->options };

#
#  map options to form parameters
#

$options{p} = 'blastp';
$options{d} = 'GO';
$options{e} = '1e-50';
$options{i} = undef;
$options{M} = 'BLOSUM62';
$options{F} = 'T';
$options{W} = '0';
$options{g} = 'T';
$options{b} = '50';

#
# place updated options in config object
#
   $blastConfig->options( \%options );
   $self->blastconfig($blastConfig);

}


sub blast
{
my ($self, $feature_no) = @_;
my $blastConfig = $self->blastconfig();
my %options = %{ $blastConfig->options };

my $protein_sequence = $self->getSequence($feature_no);

if(!$protein_sequence)
{
   return;
}
else
{
    print "Herez the protein sequence   ".$protein_sequence."\n";
}


$options{i} = $protein_sequence;

$blastConfig->options( \%options );

if ( $blastConfig->server_down ) {

   $blastConfig->page_header();
   print "Sorry for the inconvenience, but the BLAST server is temporarily unavailable.";
   $blastConfig->page_footer();

}
else
{
   my $report = $blastConfig->blast_server->blastall( %{$blastConfig->options} );

  #
  # If filesize error (file too big for current SOAP::Lite to transfer
  #  in a reasonable amount of time), ftp file to tmp directory and
  #  allow the user to download this file.  (Large files would also slow down
  #  server trying to parse a huge file.)
  #
   if ( $report->fault and $report->faultcode eq 'SOAP-ENV:Server.FileSize' ) {
     #
     #  location of file : $report->faultdetail->{location}
     #  size of file     : $report->faultdetail->{size}
     #

      my $size            = $report->faultdetail->{BlastSizeError}->{size};
      my $remote_location = $report->faultdetail->{BlastSizeError}->{location};

      my $local_filename  = "$$.blast";

      my $sftp = new Net::SFTPW32($blastConfig->blast_host, user=>$blastConfig->sftp_user, password =>$blastConfig->sftp_pw, protocol => 2 );

      $sftp->get( $remote_location, $blastConfig->tmp_dir.$local_filename );

      $blastConfig->page_header();

      print $report->faultstring."\n";

      print "Sorry, but currently we do not HTML format a report if it is this large."."\n";
      print a({-href=>$blastConfig->tmp_url.$local_filename},"download text file here.");

      my $sftp = new Net::SFTPW32($blastConfig->blast_host, user=> $blastConfig->sftp_user, password => $blastConfig->sftp_pw, protocol => 2 );
      $sftp->do_remove( $remote_location );

      $blastConfig->page_footer();

   }
   elsif ($report->fault) {

      $blastConfig->page_header();

      print 'ERROR:<font class="red">';

      if ( $report->faultcode ne 'SOAP-ENV:Server.Custom' ) {
         print "Sorry, an error occured on our server.  Please email this bug to ".$blastConfig->email." and include the following information:"."\n";
      }
      print $report->faultstring;

      print "</font>";
      $blastConfig->page_footer();

   }
   else {

    my $report_text  = $report->result();
    my $stringio = IO::String->new( $report_text );
    my $searchio   = Bio::SearchIO->new('-fh'     => $stringio,
                                     '-format'  => 'blast');

     while ( my $result = $searchio->next_result() )
       {

               while( my $hit = $result->next_hit )
               {
                        my $hit_name = $hit->name();
                         my $desc = $hit->description();
                         my $gp = new GO::GOGeneAssociationParser;
                         $gp->set_info($desc);
                         my @gaarr = $gp->parse();
                         my $len = $hit->length();
                         my $ag = $hit->algorithm();
                         my $score = $hit->raw_score();
                         my $significance = $hit->significance();
                         my $rank = $hit->rank();
                         my $blast_info = new GO::GOGeneBlastInfo(rank => $rank, significance => $significance, score => $score, length => $len);
                         print "Hit name  ".$hit_name."\n";
                         my $externaldb; ### This vaiable is used to filter out the dicty sequences
                         foreach my $goa (@gaarr)
                         {
                                 $goa->blastinfo($blast_info);
                                 my($edb,$eid) =split(/\|/,$hit_name);
                                 $goa->extdb($edb);
                                 $externaldb =$edb;
                                 ### Remove the MGI: prefix from their ID
                                 if($eid =~ /MGI/i)
                                 {
                                     $eid =~ s/MGI://g;
                                 }
                                 $goa->extdbid($eid);
                         }
                         if(!($externaldb =~ /DDB/))
                         {
                            return @gaarr;
                         }
               }
       }
   }
}

}

1;
