#!/usr/bin/perl
package sdevLoadSeq;

#######################################################################
##### Author : Mira Kaloper
##### Date   : April 2002
##### Description : This package contains all necessary methods for
#####               inserting new sequences into display_seq table.
#####
#######################################################################

use strict;
use DBI;
use CGI qw/:all/;

use lib "/usr/local/dicty/www_dictybase/db/lib/common";
use Login qw (ConnectToDatabase);
use TextUtil qw (DeleteUnwantedChar);

use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase";
use dictyBaseCentralMod qw(:formatPage :getInfo);

use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/Objects";
use ConfigURLdictyBase;

use Subfeature;
use Subfeature_type;
use Coordinate_archive;
use Feature;
use Feature_update;
use Subfeature_update;
use Note;
use Reference;
use Reflink;
use Alias;
use Feature_type;

########### 

use SubFeatureObject;
use CreateSeqPage;

use Sequence;

$| = 1;

#######################################################################
#################### global variables #################################
#######################################################################

my $dbh;
my $dblink;
my $configUrl;
my $locusObj;
my $featObj;


#######################################################################
sub new {      ############ constructor ###############################
#######################################################################

        my ($self, %args) = @_;

        $self = {};

        bless $self;

        $self->{'_database'} = $args{'database'};
        $self->{'_help'} = $args{'help'};
        $self->{'_title'} = $args{'title'};
        $self->{'_submit'} = $args{'submit'};
        $self->{'_feature'} = $args{'feature'};
        $self->{'_user'} = $args{'user'};
        $self->{'_type'} = $args{'type'};
	
        $dblink = ($self->{'_database'} =~ m/dev/i) ? "dictyBaseDEV" : "dictyBase";

        return $self;
}

sub help { $_[0]->{_help} }
sub database { $_[0]->{_database} }
sub title { $_[0]->{_title} }
sub user { $_[0]->{_user} }

######################################################################
sub DESTROY {   ############ destructor ##############################
######################################################################
        if (defined $dbh) {
                $dbh->disconnect;
        }
}


######################################################################
sub start{
######################################################################

        my ($self) = @_;

        $configUrl = ConfigURLdictyBase->new;

        my ($dbuser, $dbpasswd) = &getUsernamePassword(uc($self->{'_user'}),
                                                          $self->database);
        if (!$dbuser || !$dbpasswd) {
            print "location: ", $configUrl->dictyBaseCGIRoot,
                 $dblink,"/curatorLogin\n";
            print "Content-type: text/html\n\n";
            exit;
        }


        $dbh = &ConnectToDatabase($self->database, $dbuser, $dbpasswd);

	
	if (param('exist') && $self->{'_feature'}) {
	    
	    $self->updateSequences4existingFeature;

	    exit;

	}


        if (!$self->{'_type'}) {
            $self->printEntryForm;
            exit;
        }

        $self->setVariables;


        if ($self->{'_type'} eq 'enterFeature') {
            $self->displayFeatureForm;
            exit;
        }

        if ($self->{'_type'} eq 'subFeatureCoordEntry') {
           $self->confirmSubfeatureEntry;
           exit;
        }

        if ($self->{'_type'} eq 'subFeatureCoordInsert') {
           $self->insertSubfeatureEntry;
           exit;
        }

}

#######################################################################
sub printEntryForm {
#######################################################################
        my ($self) = shift;

        &printStartPage($self->database, $self->title, $self->help);

        print center(table({-border=>3,
                        -cellpadding=>4,
                        -cellspacing=>4},

                       Tr({-align=>'LEFT'},
                          [
                           td({-bgcolor=>"#b7d8e4",
                               -width=>350},
                              table({-border=>0},
                                    Tr({align=>'LEFT'},
                                       [
                                        td(start_form,
                                           "Enter feature: ").
                                        td(textfield(-name=>'feature',
                                                     -size=>'15')),
                                        hidden(-name=>'user',
                                                -value=>$self->{'_user'}),
                                        hidden(-name=>'type',
                                               -value=>'enterFeature'),
					hidden(-name=>'exist',
					       -value=>param('exist')),
                                        td("&nbsp;").
                                        td(submit(-name=>'submit',
                                                  -value=>'Submit'), reset, end_form)
                                        ]))
                              )
                           ])));

        &printEndPage;

}

########################################################################
sub displayFeatureForm {
########################################################################
  my $self = shift;

  &printStartPage($self->database, $self->title, $self->help);


  my $start = $self->{'_start'};
  my $stop =  $self->{'_stop'};

  print "\n", start_form;


  if ($self->checkSubFeatureExists) {
      print "This feature has alredy subfeatures entered in the database.",
            " You cannot create new sequences for this subfeature. \n";
      &printEndPage; 
      return;
  }

  $self->printFeatureHeading(1);


  #### In order to check the start and stop coords, we need to call this ...
  my $seqObject = CreateSeqPage->new(dbh=>$dbh,
                             database=>$self->{'_database'},
                             chrnum=>$self->{'_chr'},
                             feature=>$self->{'_feature'},
                             user=>user,
                             start=>$start,
                             stop=>$stop);

  if (!$seqObject) {
     print "Could not create CreateSeqPage object \n";
     exit;
  }


#  $self->{'_genomicDNA'} = $seqObject->getGenomicDNASequence;
#  $self->{'_genomic1KDNA'} = $seqObject->getGenomic1KDNASequence;
#  $self->{'_codingDNA'} = $seqObject->getCodingDNASequence;
#  $self->{'_protein'} = $seqObject->getProteinSequence;


  print hidden(-name=>'feature',
               -value=>$self->{'_feature'});

  print hidden(-name=>'user',
               -value=>$self->{'_user'});

  if ($self->{'_feature'} =~ /^ARS/i) {

#     print hidden(-name=>'exist',
#		   -value=>'1');

      param('exist', '1');

      print hidden('exist');

  }
  
  param('type','subFeatureCoordEntry');

  print hidden('type');

  print br;

  print submit(-name=>'submit', -value=>'Submit'), " ", reset;  

  print "\n", end_form;
 
  &printEndPage;

}


########################################################################
sub checkSubFeatureExists {
########################################################################
  my $self = shift;

  my @subfeatureArray = Subfeature->GetStartStopArray(dbh=>$dbh,
                                          feature_no=>$self->{'_feature_no'});

  my $arraySize = $#subfeatureArray + 1;

  return $arraySize;
}


########################################################################
sub confirmSubfeatureEntry {
########################################################################
  my $self = shift;

  &printStartPage($self->database, $self->title, $self->help);


  my $start = $self->{'_start'};
  my $stop =  $self->{'_stop'};

  #check for gaps in the subfeature coordinates...
  my $subFeatureObj = SubFeatureObject->new(dbh=>$dbh,
                                               database=>$self->{'_database'},
                                               chrnum=>$self->{'_chr'},
                                               feature=>$self->{'_feature'},
                                               user=>user,
                                               new_start=>$self->{'_start'},
                                               new_stop=>$self->{'_stop'},
                                               type=>$self->{'_type'});


   if (!$subFeatureObj) {
        print "Could not create SubFeatureObject \n";
        exit;
   }


  $subFeatureObj->checkChangeSubFeatureError;



  print "\n", start_form;

  $self->printFeatureHeading;

  param('type','subFeatureCoordInsert');

  print hidden(-name=>'feature'),
        hidden(-name=>'user'),
        hidden(-name=>'type'), p,
        submit(-name=>'submit',
               -value=>'Submit');

  my $i=1;


  my $subFeatureObj = SubFeatureObject->new(dbh=>$dbh,
                                               database=>$self->{'_database'},
                                               chrnum=>$self->{'_chr'},
                                               feature=>$self->{'_feature'},
                                               user=>user,
                                               new_start=>$self->{'_start'},
                                               new_stop=>$self->{'_stop'},
                                               type=>$self->{'_type'});


   if (!$subFeatureObj) {
        print "Could not create SubFeatureObject \n";
        exit;
   }


  $subFeatureObj->printHiddenCoordChanges;

  print end_form;

 
  &printEndPage;


}

########################################################################
sub insertSubfeatureEntry {
########################################################################
  my $self = shift;

  &printStartPage($self->database, $self->title, $self->help);

  my $feature = $self->{'_feature'};
  print h4("Feature Name:  $feature");


  eval {

    $self->loopInsertSubFeatureCoord('Exon');
    $self->loopInsertSubFeatureCoord('Intron');


    #deletes and inserts sequences that has changed into display_seq table
    $self->updateSequences;


  };

  if ($@) {
      print "An Error Occurred!: $@";
      $dbh->rollback;
      $dbh->disconnect;
      exit(1);

  } else {
    $dbh->commit;
    #$dbh->rollback;
    print p, h4("Database has been updated sucessfully");
  }




  &printEndPage;

}


#########################################################################
sub loopInsertSubFeatureCoord {
#########################################################################
  my ($self,$type) = @_;

  my $feature_no = $self->{'_feature_no'};

  my $i = 1;
  my $heading = $type . $i;
  while (param("$heading")) {
    my $value = param("$heading");
    my($start, $stop) = split (/:/,$value);

    print "Inserting new $type into subfeature with $start-$stop coordinate", br;
    Subfeature->Insert(dbh=>$dbh,
                     literals=>{SUBFEATURE_NO=>'CGM_DDB.SUBFEATNO_SEQ.NEXTVAL',
                                DATE_CREATED=>'SYSDATE'},
               binds=>{FEATURE_NO=>$self->{'_feature_no'},
                       START_COORD=>$start,
                       STOP_COORD=>$stop,
                       CREATED_BY=>$self->{'_user'}});

    my $subFeatureNo = $self->getSubFeatureNo;

    print "Inserting $type into subfeature_type table", br;

    Subfeature_type->Insert(dbh=>$dbh,
                            literals=>{SUBFEATURE_NO=>$subFeatureNo,
                                       DATE_CREATED=>'SYSDATE'},
                      binds=>{SUBFEATURE_TYPE=>$type,
                              CREATED_BY=>$self->{'_user'}});


    $i++;
    $heading = $type . $i;
 
  }
}




########################################################################
sub updateSequences {
########################################################################
  my $self = shift;


  #create sequeces...
  my $start = param('new_start');
  my $stop =  param('new_stop');


  print "start = $start", br;

  print "stop = $stop", br;

  my $seqObject = CreateSeqPage->new(dbh=>$dbh,
                             database=>$self->{'_database'},
                             chrnum=>$self->{'_chr'},
                             feature=>$self->{'_feature'},
                             user=>user,
                             start=>$start,
                             stop=>$stop);

  if (!$seqObject) {
     print "Could not create CreateSeqPage object \n";
     exit;
  }

  my $genomicDNA = $seqObject->getGenomicDNASequence;
  my $genomic1KDNA = $seqObject->getGenomic1KDNASequence;
  my $codingDNA = $seqObject->getCodingDNASequence;
  my $protein = $seqObject->getProteinSequence;

  $self->insertSequence('Genomic DNA',$genomicDNA);
  $self->insertSequence('Genomic DNA +/- 1000bp',$genomic1KDNA);

  #ORF and RNA will have coding sequence
  if (($self->{'_feature_type'}=~ /ORF/) || 
      ($self->{'_feature_type'}=~ /RNA/)) {
       $self->insertSequence('DNA coding sequence',$codingDNA);
  }


  #only ORF will have protein sequence
  if ($self->{'_feature_type'}=~ /ORF/) { 
     $self->insertSequence('Protein',$protein);
  }

}

########################################################################
sub updateSequences4existingFeature {
########################################################################
### added by shuai for updating the sequence for an existing feature
########################################################################
  my ($self) = shift;

  &printStartPage($self->{'_database'}, "Update Sequence");

  my $featObj = Feature->new(dbh=>$dbh,
			     feature_name=>$self->{'_feature'});
  
  if (!$featObj) {

      print "The feature_name ".$self->{'_feature'}." is not found in database.";
      exit;

  }

  print "feature_name = ".$featObj->feature_name, br;
  print "start_coord = ".$featObj->start_coord, br;
  print "stop_coord = ".$featObj->stop_coord, br;

  my $seqObject = CreateSeqPage->new(dbh=>$dbh,
                             database=>$self->{'_database'},
                             chrnum=>$featObj->chromosome,
                             feature=>$featObj->feature_name,
                             user=>$self->{'_user'},
                             start=>$featObj->start_coord,
                             stop=>$featObj->stop_coord);

  if (!$seqObject) {
     print "Could not create CreateSeqPage object", p;
     exit;
  }

  my $genomicDNA = $seqObject->getGenomicDNASequence;
  my $genomic1KDNA = $seqObject->getGenomic1KDNASequence;
  my $codingDNA = $seqObject->getCodingDNASequence;
  my $protein = $seqObject->getProteinSequence;

  if (!$genomicDNA) {
      
      print "Could not create genomic DNA sequence", p;
      exit;
  }

  eval { $self->deleteSequence($featObj->feature_no); };

  if ($@) {
      
      print "Error occurred when deleting sequence for ".$featObj->feature_name." from display_seq table.:$@",p;
      $dbh->rollback;
      exit;

  }
  
  eval { 

      $self->{'_feature_no'} = $featObj->feature_no;

      $self->insertSequence('Genomic DNA',$genomicDNA);
      $self->insertSequence('Genomic DNA +/- 1000bp', $genomic1KDNA);

      if ($featObj->featureTypeList =~ /(ORF|RNA)/i) {
	  $self->insertSequence('DNA coding sequence', $codingDNA);
      }

      if ($featObj->featureTypeList =~ /ORF/i) { 
	  $self->insertSequence('Protein', $protein);
      }
  };
  if ($@) {

      print "Error occurred when inserting sequence for ".$featObj->feature_name." into display_seq table.:$@",p;
      $dbh->rollback;
      exit;

  }
  $dbh->commit;

  print "The sequences for ".$featObj->feature_name." in display_seq table have been updated.",p;

  &printEndPage;

}

########################################################################
sub deleteSequence {
########################################################################
    my ($self, $featNo) = @_;

    my $sth = $dbh->prepare("
        DELETE from CGM_DDB.display_seq
        WHERE  feature_no = ?
    ");
    $sth->execute($featNo);
    
    $sth->finish;

}

########################################################################
sub insertSequence {
########################################################################
  my ($self, $type, $sequence) = @_;


  my $seqlen = length($sequence);

  my $dbuser = $self->{'_user'};

  print "Updating $type sequence ... \n", br;

  Display_seq->Insert(dbh=>$dbh,
                   literals=>{display_seq_no=>'CGM_DDB.DISPLAYSEQNO_SEQ.NEXTVAL',
                              DATE_CREATED=>'SYSDATE'},
                   binds=>{FEATURE_NO=>$self->{'_feature_no'},
                           DISPLAY_SEQ_TYPE=>$type,
                           SEQ_LENGTH=>$seqlen,
                           CREATED_BY=>$dbuser,
                           DISPLAY_SEQ=>$sequence});

}
 

########################################################################
sub getSubFeatureNo {
########################################################################
  my $self = shift;

  my $sth = $dbh->prepare(  "SELECT CGM_DDB.SUBFEATNO_SEQ.currval
                                    FROM dual");

  $sth->execute();
  my $subFeatureNo = $sth->fetchrow;
  $sth->finish;

  return $subFeatureNo;

}


########################################################################
sub printFeatureHeading {
########################################################################
   my ($self, $new) = @_;

   my $locus;
   $locus = "/" . $self->{'_locus_name'} if ($self->{'_locus_name'});

   print h4($self->{'_feature'} . $locus);

   my @rows;
   my $string;

   if ($new && $self->{'_feature'} !~ /^ARS/i) {
      @rows = $self->getEmptyRows; 
   } else {

     my $subFeatureObj = SubFeatureObject->new(dbh=>$dbh,
                                                 database=>$self->{'_database'},
                                                 chrnum=>$self->{'_chr'},
                                                 feature=>$self->{'_feature'},
                                                 type=>$self->{'_type'});


      if (!$subFeatureObj) {
          print "Could not create SubFeatureObject \n";
          exit;
      }

      @rows = $subFeatureObj->printNewSubFeature;
      my $subFeatureParam = $subFeatureObj->getSubFeatureParam;

      $string = th('Genomic DNA') .  td({colspan=>2, align=>'center'}, $self->getLinkToNewGenomicDNA($subFeatureParam));

      $string .= "<TR>";
      $string .= th('DNA + 1 kb up/downstream') .  td({colspan=>2, align=>'center'}, $self->getLinkToNewGenomic1K($subFeatureParam));
      $string .= "<TR>";

      #ORF and RNA will have coding sequence
      if (($self->{'_feature_type'}=~ /ORF/) || 
         ($self->{'_feature_type'}=~ /RNA/)) {
     
         $string .= th({align=>'left'},'Coding Sequence') . td({colspan=>2, align=>'center'}, $self->getLinkToNewCodingDNA ($subFeatureParam));
         $string .= "<TR>";
      }


      #only ORF will have protein sequence
      if ($self->{'_feature_type'}=~ /ORF/) {
          $string .= th({align=>'left'},'Protein') . td({colspan=>2, align=>'center'}, $self->getLinkToNewProtein($subFeatureParam));
          $string .= "<TR>";
      }


      #$string .= th('6FrameTranslation(Genomic)') . td({colspan=>2, align=>'center'}, $self->getLinkToNew6FrameTranslation($subFeatureParam));

   }

   print table({-border=>3,
                -cellpadding=>4,
                -cellspacing=>4,
                -bgcolor=>"#b7d8e4"},

                Tr({-align=>'LEFT'},
                  [
                    th(br) . th({-align=>'center',colspan=>2},'New Info '), 
                    th('Chromosome ') . td({colspan=>2},$self->{'_chr'}),
                    th('Start ') . td({colspan=>2},$self->{'_start'}),
                    th('Stop ') . td({colspan=>2},$self->{'_stop'}),
                    th('Strand ') . td({colspan=>2},$self->{'_strand'}),
                    @rows,
                    $string
      ]));


}


########################################################################
sub getEmptyRows {
########################################################################
  my ($self) = @_;


  my @rows;
  my $i = 3;

  my $k = 1;

  while ($k <= $i) {
    push(@rows, $self->getSubFeatureEntry("Exon$k"));
    push(@rows, $self->getSubFeatureEntry("Intron$k"));
    $k++;
  }
  
  push(@rows, $self->getSubFeatureEntry("Exon$k"));

  return @rows;

}



#######################################################################
sub getSubFeatureEntry {
#######################################################################
  my ($self, $name, $default) = @_;

  my ($start,$stop,$no) = split(/:/,$default);

  #have to display one more exon...
  my $field =  td(b($name)) .
               td(textfield(-name=>$name. '_start',
                            -size=>15,
                            -value=>$start)) .
               td(textfield(-name=>$name . '_stop',
                            -size=>15,
                           -value=>$stop));

  return $field;
}


########################################################################
sub setVariables {
########################################################################
    my ($self) = @_;

    $self->{'_feature'} = uc($self->{'_feature'});

    my $feature = $self->{'_feature'};

    &DeleteUnwantedChar(\$feature);

    $self->{'_feature'} = $feature;


    if ($feature) {

        my $featureObj = Feature->new(dbh=>$dbh,
                                       feature_name=>$feature);
        if (!$featureObj) {
            &printStartPage($self->database, $self->title, $self->help);
            $self->err_report("There is no feature_name associated with $feature in the database.");
        }

        $self->{'_feature_no'} = $featureObj->feature_no;
        $self->{'_chrnum'} = $featureObj->chromosome;
        $self->{'_beg'} = $featureObj->start_coord;
        $self->{'_end'} = $featureObj->stop_coord;
        $self->{'_locus_name'} = $featureObj->locus_name;
        $self->{'_chr'} = $featureObj->chromosome;
        $self->{'_start'} = $featureObj->start_coord;
        $self->{'_stop'} = $featureObj->stop_coord;
        $self->{'_strand'} = $featureObj->strand;
        $self->{'_feature_version'} = $featureObj->feature_version;
        $self->{'_feature_type'} = $featureObj->featureTypeList; 

    }

}




#######################################################################
sub getLinkToNewGenomicDNA {
#######################################################################
  my ($self,$subFeatureParam) = @_;

  return a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/curation/createSeqPage.pl?user=$self->{'_user'}&feature=$self->{'_feature'}&seqtype=genomicDNA&start=$self->{'_start'}&stop=$self->{'_stop'}&action=getSequence&type=New&$subFeatureParam", -target=>'new_seq_window'},"Display"), br;

}


########################################################################
sub getLinkToNewCodingDNA {
########################################################################
  my ($self,$subFeatureParam) = @_;

  return a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/curation/createSeqPage.pl?user=$self->{'_user'}&feature=$self->{'_feature'}&seqtype=codingDNA&start=$self->{'_start'}&stop=$self->{'_stop'}&action=getSequence&type=New&$subFeatureParam", -target=>'new_seq_window'},"Display"), br;

}


########################################################################
sub getLinkToNewProtein {
########################################################################
  my ($self, $subFeatureParam) = @_;

  return a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/curation/createSeqPage.pl?user=$self->{'_user'}&feature=$self->{'_feature'}&seqtype=protein&start=$self->{'_start'}&stop=$self->{'_stop'}&action=getSequence&type=New&$subFeatureParam", -target=>'new_seq_window'},"Display"), br;

}


########################################################################
sub getLinkToNewGenomic1K {
########################################################################
  my ($self,$subFeatureParam) = @_;


  return a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/curation/createSeqPage.pl?user=$self->{'_user'}&feature=$self->{'_feature'}&seqtype=genomic1KDNA&start=$self->{'_start'}&stop=$self->{'_stop'}&action=getSequence&type=New&$subFeatureParam", -target=>'new_seq_window'},"Display"), br;

}




########################################################################
sub err_report {
########################################################################
    my ($self, $err) = @_;

    print font({-size=>"+1",-color=>"red"},"$err!\n"), br;

    &printEndPage;

    $dbh->disconnect;
    exit;
}


########################################################################
1; #####################################################################
########################################################################




