package SubFeatureObject;

#######################################################################
##### Author : Mira Kaloper	
##### Date   : May 24 2002
##### Description : This package contains all necessary methods for 
#####               creating and displaing subfeatures: Intron and Exsons. 
#####              
#######################################################################
use strict;
use DBI;
use CGI qw/:all/;
# use CGI::Carp qw(fatalsToBrowser);
use lib "/usr/local/dicty/www_dictybase/db/lib/common";
use Login qw (ConnectToDatabase);

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

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


$| = 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->{'_feature'} = $args{'feature'};
  $self->{'_new_start'} = $args{'new_start'};
  $self->{'_new_stop'} = $args{'new_stop'};
  $self->{'_update_type'} = $args{'type'}; 

  $dblink = ($self->{'_database'} =~ m/dev/i) ? "dictyBaseDEV" : "dictyBase"; 

  $dbh = &ConnectToDatabase($self->database);
  $self->setVariables;

  $self->setSubFeature;

  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 setSubFeature {
#######################################################################
  my $self = shift;

  $self->setSubFeatureDef;

  if ($self->{'_update_type'} eq 'changeFeatureCoord') {
     $self->setSubFeatureForChangeFeatureCoord;
  }
 
  #remove ($self->{'_update_type'} eq 'subFeatureCoordEntry') perhaps...
  if (($self->{'_update_type'} eq 'changeSubFeatureCoord') 
     || ($self->{'_update_type'} eq 'subFeatureCoordEntry')){

     $self->setSubFeatureForChangeSubFeatureCoord;
  }

  if ($self->{'_update_type'} eq 'mergeFeatures') {
     $self->setMergeFeatures;
  }

}


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

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

  my @subfeatureArray = Subfeature->GetStartStopArray(dbh=>$dbh,
                                                     feature_no=>$feature_no);

  my $arraySize = $#subfeatureArray + 1;
  my $heading;
  my $i = 1;

  foreach my $element (@subfeatureArray) {
    my ($start, $stop, $type, $subfeature_no ) = split(/\|/,$element);

    if ($type eq "Exon") {
       $heading = $type . $i;
    } else {
       $heading = $type . $i++;
    }

    #set exon/intron info
    $self->{"_$heading"} = "$start:$stop:$subfeature_no";
  }


  $self->{'_numOfExons'} = $i;

}

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

  if (!$self->{"_new_start"} && !$self->{"_new_stop"}) {
      return;
  }

  #check start and stop coordinates
  if ($self->{'_strand'} eq 'C') {
     if ($self->{"_new_start"} < $self->{"_new_stop"}){
        $self->err_report("Start coord must be bigger than stop coord");
        exit; 
     }
  } else {
     if ($self->{"_new_start"} > $self->{"_new_stop"}){
        $self->err_report("Stop coord must be bigger than start coord"); 
        exit;
     }
   
  }

  my ($startDiff, $stopDiff);

  $startDiff = $self->{'_start'} - $self->{'_new_start'}
                        if ($self->{'_new_start'});

  $stopDiff = $self->{'_new_stop'} - $self->{'_stop'}
                        if ($self->{'_new_stop'});

  my $crick = 1;
  if ($self->{'_strand'} eq 'C') {
     $crick = -1;
  }



  my ($first_intron_start, $first_intron_stop);

###process introns
  my $i = 1;
  my $first_time = 1;
  my $save_intron = 'Y';
  while ($self->{"_Intron$i"}) {
    my ($start, $stop, $subfeature_no ) = split(/\:/,$self->{"_Intron$i"});

    print "in intron: $start, $stop, $subfeature_no ", br;

    #skip introns that should not be in new subfeatures
    if ($self->{'_strand'} eq 'C') {
       if ($self->{'_start'} - $stop > $self->{'_new_start'}) {
           print "skip intron $i: $stop ", $self->{'_start'} - $stop, " ", $self->{'_new_start'}, br; 
           $i++;
           next;
       }

      #check if intron is outside of range...
      if ($self->{'_start'} - $stop < $self->{'_new_stop'}) {
           print "skip intron here $i: $stop ", $self->{'_start'} - $stop , " ",  $self->{'_new_stop'},br;
           $i++;
           last;
       }

    } else {
       if ($self->{'_start'} + $stop < $self->{'_new_start'}) {
           print "exit $i: $stop ", br;

           $i++;
           next;
       }

      #check if intron is outside of range...
      if ($self->{'_start'} + $stop > $self->{'_new_stop'}) {
           print "exit $i: $stop ", br;
           $i++;
           last;
       }


    }


      #save start of intron
      if ($save_intron eq 'Y') { 
        $first_intron_start = $start;
        $first_intron_stop = $stop;
        $save_intron = 'N';
      }  

      my $start = $start+$startDiff*$crick;
      my $stop = $stop+$startDiff*$crick;

      #$self->{"_new_Intron$i"} = "$start:$stop:$subfeature_no";
      $self->{"_new_Intron$first_time"} = "$start:$stop:$subfeature_no";
      print "_new_Intron$first_time = $start:$stop:$subfeature_no", br;
      $i++;
      $first_time++;
  }


  my $shiftIntron;


  my $intron_diff = $first_intron_stop; #- $startDiff;

  if ($first_intron_stop) {
     $intron_diff = $first_intron_stop - $startDiff;
  }
  print "first_intron_start = $first_intron_start first_intron_stop = $first_intron_stop", br;

###process exons
  my $first_time = 1;
  my $i = 1; 
  while ($self->{"_Exon$i"}) {
   
    my ($start, $stop, $subfeature_no ) = split(/\:/,$self->{"_Exon$i"});

    print "old exon coords: $start, $stop",br;
    
    print "new_start = ", $self->{'_new_start'}, br;
    print "new_stop = ", $self->{'_new_stop'}, br;

    #skip exons that should not be in new subfeatures
    if ($self->{'_strand'} eq 'C') {
       if ($self->{'_start'} - $stop >= $self->{'_new_start'}) {
           print "$i: $stop ", br;
           $i++;
           next;
       }

      #check if exon is outside of range...
      if ($self->{'_start'} - $start < $self->{'_new_stop'}) {
           print "skip exon $i: $stop ", br;
           $i--;

           #ajust exon stop coord since it ma extend to cover intron
           if ($self->{"_new_Exon$i"}){
              my ($estart, $estop,$esubfeature_no) = split(/:/,$self->{"_new_Exon$i"});
              $estop =  $self->{'_new_start'} - $self->{'_new_stop'} + 1 ;

              $self->{"_new_Exon$i"} = "$estart:$estop:$esubfeature_no";
           }

           last;
       }


    } else {
       print "$i: $self->{'_start'},  $stop, $self->{'_new_start'}", br; 
       if ($self->{'_start'} + $stop <= $self->{'_new_start'}) {
           print "$i: $stop ", br;

           $i++;
           next;
       }

      #check if exon is outside of range...
      if ($self->{'_start'} + $start > $self->{'_new_stop'}) {
           print "Hi there", br; 
           print "exit $i: $stop ", br;
           $i--;

           #ajust exon stop coord since it ma extend to cover intron
           if ($self->{"_new_Exon$i"}){
             my ($estart, $estop,$esubfeature_no) = split(/:/,$self->{"_new_Exon$i"});
             $estop =  $self->{'_new_stop'} - $self->{'_new_start'} + 1 ;

             $self->{"_new_Exon$i"} = "$estart:$estop:$esubfeature_no";
           }
  
           last;
       }


    }

    print "$start, $stop, $subfeature_no", br;
 
    if ($first_time == 1) {
       #$start = 1;
       my $nextVal = $i + 1;
       if ($self->{"_Exon$nextVal"}) {

          #$stop = $stop + $startDiff*$crick;
          #we have cut in the middle of intron =>  join intron with exon
          if ($first_intron_start <= $start) {
            #remove first intron 
            $shiftIntron = 1;
            print "intron_diff = ", $intron_diff, br;

            $stop = $stop  - $start + $intron_diff; # +1 
          } else {
            #$stop = $stop + $startDiff*$crick - $start + 1;
            print "startDiff = $startDiff, crick = $crick", br; 
            $stop = $stop + $startDiff*$crick; # + 1;
          }
          $start = 1;
       } else {
         #$stop = $stop + $stopDiff*$crick + $startDiff*$crick;
         #we have cut in the middle of intron =>  join intron with exon
           if ($first_intron_start <= $start) {
                 $shiftIntron = 1;

            print "I am here", br;

            print "intron_diff = $intron_diff", br;
            print "stop = $stop",br;
            print "start = $start " , br;

            $stop  = $stop + $stopDiff*$crick +$startDiff*$crick;# + $intron_diff;
          } else {
            print "I am here here", br;

            $stop = $stop + $stopDiff*$crick + $startDiff*$crick - $start + 1;
          }

         $start = 1;

         
       }
       $self->{"_new_Exon$first_time"} = "$start:$stop:$subfeature_no";
       $first_time++;
 
    } else {

      print 'I am in else... ', br;

      my $start = $start+$startDiff*$crick;
      my $stop = $stop+$startDiff*$crick;

      my $nextVal = $i + 1;  
      if (!($self->{"_Exon$nextVal"})) {
          $stop = $stop + $stopDiff*$crick;
      }

      $self->{"_new_Exon$first_time"} = "$start:$stop:$subfeature_no";
      $first_time++;
   
    }   

    $i++;

  }

  
  if (!$self->{"_new_Exon1"}) {
     if ($self->{'_strand'} eq 'C') { 
       my $start = 1;
       print "new_start = ", $self->{'_new_start'}, br;
       print "new_stop = ", $self->{'_new_stop'}, br;

       my $stop = $self->{'_new_start'} - $self->{'_new_stop'} +1;
       $self->{"_new_Exon1"} = "$start:$stop:" ;

     } else {
       my $start = 1;
       print "new_start = ", $self->{'_new_start'}, br;
       print "new_stop = ", $self->{'_new_stop'}, br;
       my $stop = $self->{'_new_stop'} - $self->{'_new_start'} +1;
       $self->{"_new_Exon1"} = "$start:$stop:" ;
     }
      
  }

  #shift introns when required
  my $i = 1;

  if ($shiftIntron == 1) {
     while ($self->{"_new_Intron$i"}) {
        my $j = $i+1;
        if ($self->{"_new_Intron$j"}) {
           $self->{"_new_Intron$i"} = $self->{"_new_Intron$j"};
        } else {
           undef $self->{"_new_Intron$i"};
        }
        $i++;
     }  
  }

}


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

  my @array;

  my $i = 1;
  while ($self->{"_new_Exon$i"}) {
    push(@array, "_Exon$i:" . $self->{"_new_Exon$i"});
    $i++;
  }

  return @array; 

}


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

  my @array;

  my $i = 1;
  while ($self->{"_new_Intron$i"}) {
    push(@array, "_Intron$i:" . $self->{"_new_Intron$i"});
    $i++;
  }

  return @array;

}


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

  #if no change yet exit
  if (!param("Exon1_start")) {
     return;
  }

  my $i = 1;

  while (param("Intron".$i."_start")) {
     #missing subfeature_no....
     my $start = param("Exon".$i."_start");
     my $stop = param("Exon".$i."_stop"); 
 
     my ($old_start,$old_stop,$subfeature_no) = split(/:/,param("Exon".$i)); 

     $self->{"_new_Exon$i"} = "$start:$stop:$subfeature_no";

     $start = param("Intron".$i."_start");
     $stop = param("Intron".$i."_stop");

     ($old_start,$old_stop,$subfeature_no) = split(/:/,param("Intron".$i));

     $self->{"_new_Intron$i"} = "$start:$stop:$subfeature_no";

     $i++;
  }

  my ($old_start,$old_stop,$subfeature_no) = split(/:/,param("Exon".$i));
  my $start = param("Exon".$i."_start");
  my $stop = param("Exon".$i."_stop"); 

  if (!$start && !$stop) {
     $self->err_report("Subfeature must finish with Exon");
     exit;
  }

  $self->{"_new_Exon$i"} = "$start:$stop:$subfeature_no";

  $self->{'_numOfNewExons'} = $i;

}


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


  #if no change yet exit
  if (!param("Exon1_start")) {
     return;
  }

  my $i = 1;

  while (param("Intron".$i."_start")) {
     #missing subfeature_no....
     my $start = param("Exon".$i."_start");
     my $stop = param("Exon".$i."_stop");

     my ($old_start,$old_stop,$subfeature_no) = split(/:/,param("Exon".$i));

     $self->{"_new_Exon$i"} = "$start:$stop:$subfeature_no";

     $start = param("Intron".$i."_start");
     $stop = param("Intron".$i."_stop");

     ($old_start,$old_stop,$subfeature_no) = split(/:/,param("Intron".$i));

     $self->{"_new_Intron$i"} = "$start:$stop:$subfeature_no";

     $i++;
  }

  my ($old_start,$old_stop,$subfeature_no) = split(/:/,param("Exon".$i));
  my $start = param("Exon".$i."_start");
  my $stop = param("Exon".$i."_stop");

  if (!$start && !$stop) {
     $self->err_report("Subfeature must finish with Exon");
     exit;
  }

  $self->{"_new_Exon$i"} = "$start:$stop:$subfeature_no";

  $self->{'_numOfNewExons'} = $i;


}



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

   
  my $i = 1;

  while ($self->{"_new_Intron$i"}) {
    my ($start, $stop, $subfeature_no) = split(/:/,$self->{"_new_Exon$i"});

    my ($sec_start,$sec_stop,$sec_subfeature_no) = split(/:/,param("secExon".$i));

    $self->{"_new_Exon$i"} = "$start:$stop:$sec_subfeature_no";


    ($start, $stop, $subfeature_no) = split(/:/,$self->{"_new_Intron$i"});

    my ($sec_start,$sec_stop,$sec_subfeature_no) = split(/:/,param("secIntron".$i));

    $self->{"_new_Intron$i"} = "$start:$stop:$sec_subfeature_no";


     $i++;
  }

  my ($start, $stop, $subfeature_no) = split(/:/,$self->{"_new_Exon$i"});

  my ($sec_start,$sec_stop,$sec_subfeature_no) = split(/:/,param("secExon".$i));

  $self->{"_new_Exon$i"} = "$start:$stop:$sec_subfeature_no";


}

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

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

    &DeleteUnwantedChar(\$feature);

    if ($feature) {
        
        my $featureObj = Feature->new(dbh=>$dbh, feature_name=>$feature); 


	if (!$featureObj) {
	    $self->err_report("There is no feature associated with $feature in database.");
            exit;
	}
   
        $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;
    }

}



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

  my $i=1;
  my $sum;
  while ($self->{"_new_Exon$i"}) {
      my ($start,$stop,$seq_no) = split(/:/,$self->{"_new_Exon$i"});
      $sum += $stop - $start + 1;
      $i++;
      
      print "new exon coords : $start,$stop", br;

  }
  #check if sum is divisible by 3
  if ($sum % 3) {
     print p, font({-size=>"+1",-color=>"red"},"The exon coordinates are no longer evenly divisible by three!"), br;

    return 1; #indicates possible error
  }

  return 0;
}

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

  my $i=1;
  my $exon = "Exon".$i; 
  my $intron = "Intron".$i;

  my @rows;

  while ($self->{"_$intron"}) {
    my $value = $self->getStartStop($exon);
    push(@rows,$value);
    $value = $self->getStartStop($intron);
    push(@rows,$value);

    $i++;
    $exon = "Exon".$i;
    $intron = "Intron".$i;
  }

  my $value = $self->getStartStop($exon);
  push(@rows,$value); 


  while ($self->{"_new_$intron"}) {
    #my $value = $self->getStartStop($exon);
    #push(@rows,$value);
    my $value = $self->getStartStop($intron);
    push(@rows,$value);

    $i++;
    $exon = "Exon".$i;
    $intron = "Intron".$i;

    $value = $self->getStartStop($exon);
    push(@rows,$value);

  }

  return @rows;

}


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

  my $i=1;
  my $exon = "Exon".$i;
  my $intron = "Intron".$i;

  my @rows;
  while ($self->{"_new_$intron"}) {
    my $value = $self->{"_new_$intron"};

    $value = $self->getNewStartStop($exon);
    push(@rows,$value);

    $value = $self->getNewStartStop($intron);
    push(@rows,$value);
    $i++;
    $exon = "Exon".$i;
    $intron = "Intron".$i;

  }

  my $value = $self->getNewStartStop($exon);
  push(@rows,$value);

  return @rows;
}

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

  my $i=1;
  my $exon = "Exon".$i;
  my $intron = "Intron".$i;

  while ($self->{"_$intron"}) {

    print hidden(-name=>"$exon",
           -value=>$self->{"_$exon"});

    print hidden(-name=>"$intron",
           -value=>$self->{"_$intron"});


    $i++;
    $exon = "Exon".$i;
    $intron = "Intron".$i;
  }

  print hidden(-name=>"$exon",
           -value=>$self->{"_$exon"});

}


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

  my $i=1;
  my $exon = "Exon".$i;
  my $intron = "Intron".$i;

  while ($self->{"_$intron"}) {

    print hidden(-name=>"sec"."$exon",
           -value=>$self->{"_$exon"});

    print hidden(-name=>"sec" . "$intron",
           -value=>$self->{"_$intron"});


    $i++;
    $exon = "Exon".$i;
    $intron = "Intron".$i;
  }

  print hidden(-name=>"sec" . "$exon",
           -value=>$self->{"_$exon"});



}

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


  my @rows;

  my $i = $self->{'_numOfExons'};
  push(@rows, $self->getSubFeatureEntry("Intron$i"));
  $i++;
  push(@rows, $self->getSubFeatureEntry("Exon$i"));
  push(@rows, $self->getSubFeatureEntry("Intron$i"));
  $i++;
  push(@rows, $self->getSubFeatureEntry("Exon$i"));

  return @rows;
  
}



########################################################################
sub getStartStop {
########################################################################
  my ($self,$heading) = @_;

  my ($start,$stop,$subfature_no) = split(/:/,$self->{"_$heading"});

  my $crick = 1;
  if ($self->{"_strand"} eq 'C') {
      $crick = -1;
  }

  my ($begchr, $endchr);

  if ($start) {
     $begchr = $self->{"_start"} + $crick * ($start - 1);
     $endchr = $self->{"_start"} + $crick * ($stop - 1);
  }

  my $row = td(b($heading)).td("$start-$stop").td("$begchr-$endchr"); 

  #there is also change to intro/exon  
  if ($self->{"_new_$heading"}) {
     ($start,$stop,$subfature_no) = split(/:/,$self->{"_new_$heading"});
     my $begchr = $self->{"_new_start"} + $crick * ($start - 1);
     my $endchr = $self->{"_new_start"} + $crick * ($stop - 1);

     $row .= td("$start-$stop").td("$begchr-$endchr");
  }


  return $row;
 
}



########################################################################
sub getNewStartStop {
########################################################################
  my ($self,$heading) = @_;

  my $crick = 1;
  if ($self->{"_strand"} eq 'C') {
      $crick = -1;
  }

  my ($begchr, $endchr);

  my $row;

  #there is also change to intro/exon
  if ($self->{"_new_$heading"}) {
     my ($start,$stop,$subfature_no) = split(/:/,$self->{"_new_$heading"});
     my $begchr = $self->{"_start"} + $crick * ($start - 1);
     my $endchr = $self->{"_start"} + $crick * ($stop - 1);

     $row .= td(b($heading)) . td("$start-$stop").td("$begchr-$endchr");
  }


  return $row;

}

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

  my @rows;
  my $i = 1;  
  while ($self->{"_Intron$i"}) {
    my $field = $self->getSubFeatureEntry('Exon'.$i);
    push (@rows, $field);
    $field = $self->getSubFeatureEntry('Intron'.$i);
    push (@rows, $field);

    $i++;
  }

  #have to display one more exon...
  my $field = $self->getSubFeatureEntry('Exon'.$i);
  push (@rows, $field);

  return @rows;

}



########################################################################
sub getMergeSubFeatureChangeRows {
########################################################################
  my ($self, $otherFeature) = @_;

  my $guess = 1;

  #we know that start < other feature start
  if (($self->{'_strand'} eq 'W') 
  && ($self->{'_stop'} >= $otherFeature->{'_start'})) { 
     undef $guess;   
  }

  if (($self->{'_strand'} eq 'C') 
  && ($self->{'_stop'} <= $otherFeature->{'_start'})) { 
     undef $guess;
  }

  my @rows;
  my $i = 1;
  while ($self->{"_Intron$i"}) {
    my ($start,$stop,$no) = split(/:/,$self->{"_Exon$i"});

   # if ( ($self->{'_start'} + $stop -1) > $otherFeature->{'_start'}) {
   #    last;
   # }

    my $field;

    if ($guess) {
       $field = $self->getSubFeatureEntry('Exon'.$i,$self->{"_Exon$i"});
    } else {
       $field = $self->getSubFeatureEntry('Exon'.$i);
    }
    push (@rows, $field);

    if ($guess) {
        $field = $self->getSubFeatureEntry('Intron'.$i,$self->{"_Intron$i"});
    } else { 
        $field = $self->getSubFeatureEntry('Intron'.$i);
    }
    push (@rows, $field);

    $i++;
  }

  my ($exon_start,$exon_stop,$no) = split(/:/,$self->{"_Exon$i"});

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

  #get other feature exon/intron info...
  my @subfeatureArray = Subfeature->GetStartStopArray(dbh=>$dbh,
                                                     feature_no=>$feature_no);

  #my $i=1;
  my $heading;

  my $diff;

  my $k = 1;
 
  if ($self->{'_strand'} eq 'W') {
     $diff = $otherFeature->{'_start'} - $self->{'_stop'};
  } else {
     $diff = -$otherFeature->{'_start'} + $self->{'_stop'};
  }


  my ($start_coord, $stop_coord);

  foreach my $element (@subfeatureArray) {
    my ($start, $stop, $type, $subfeature_no ) = split(/\|/,$element);

    if (($i == 1) && ($k == 1) && ($type eq "Exon")) {
       $start_coord = 1;
       $stop_coord = $exon_stop + $diff + $stop - 1;

    } else {
      if ($k == 1) {
          $start_coord = $exon_start;
          $stop_coord = $exon_stop  + $diff + $stop - 1; 
      } else {
         $start_coord = $exon_stop +  $diff + $start - 1;
         $stop_coord = $exon_stop  + $diff + $stop - 1;
      }
    }

    $k++;

     $element =~ s/\|/:/g;
    if ($type eq "Exon") {
       $heading = $type . $i;
    } else {
       $heading = $type . $i++;
    }

    #set exon/intron info
    $element = "$start_coord:$stop_coord:$subfeature_no";


    my $field;
    if ($guess) {
        $field = $self->getSubFeatureEntry($heading,$element);
    } else {
        $field = $self->getSubFeatureEntry($heading);
    }

    push (@rows, $field);

  } 
  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 checkChangeSubFeatureError{
#####################################################################
  my $self = shift;

  my $error;

  $error = $self->checkSubFeatureStartStop;

  $error .= $self->checkSubFeatureGap;


  if ($error) {
     $self->err_report($error);
  }
}



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

  my $error;

  $error = $self->checkMergedFeatureStartStop;

  $error .= $self->checkMergedFeatureGap;


  if ($error) {
     $self->err_report($error);
  }
}

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

  my $i = 1;

  while ($self->{"_new_Intron$i"}) {
    my ($exonStart, $exonStop) = split(/\:/,$self->{"_new_Exon$i"});
    my ($intronStart, $intronStop) = split(/\:/,$self->{"_new_Intron$i"});

    if (($exonStop+1) ne $intronStart ) { 
       return "There is a gap in subfeature coordinates <P>";
    }

    $i++;

    ($exonStart, $exonStop) = split(/\:/,$self->{"_new_Exon$i"});

    if ($exonStart ne ($intronStop+1)) {
       return "There is a gap in subfeature coordinates <P>";
    }

  }
}


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

  my $i = 1;

  while ($self->{"_new_Intron$i"}) {
    my ($exonStart, $exonStop) = split(/\:/,$self->{"_new_Exon$i"});
    my ($intronStart, $intronStop) = split(/\:/,$self->{"_new_Intron$i"});

    if (($exonStop+1) ne $intronStart ) {
       return "There is a gap in subfeature coordinates <P>";
    }

    $i++;

    ($exonStart, $exonStop) = split(/\:/,$self->{"_new_Exon$i"});

    if ($exonStart ne ($intronStop+1)) {
       return "There is a gap in subfeature coordinates <P>";
    }

  }
}

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

  my $error;

  my ($start,$stop,$no) = split(/:/,$self->{"_new_Exon1"});

  #check if Exon starts with 1 and stops corresponds to Stop
  if ($start ne '1') {
     $error = "Exon should start with 1 <P>";
  }  

  my $i = 1;
  while ($self->{"_new_Exon$i"}) {
    $i++; 
  }


  $i--;

  my ($start,$stop,$no) = split(/:/,$self->{"_new_Exon$i"});

  my $crick = 1;
 
  if ($self->{'_strand'} eq 'C') {
     $crick = -1;
  }

  $stop = $self->{'_start'} + $crick *($stop - 1);

  if ($stop ne $self->{'_stop'}) { 
     $error .= "Subfeatures do not cover whole feature region"; 
  }

  return $error;
 
}


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

  my $error;

  my ($start,$stop,$no) = split(/:/,$self->{"_new_Exon1"});

  #check if Exon starts with 1 and stops corresponds to Stop
  if ($start ne '1') {
     $error = "Exon should start with 1 <P>";
  }

  my $i = 1;
  while ($self->{"_new_Exon$i"}) {
    $i++;
  }

  $i--;

  my ($start,$stop,$no) = split(/:/,$self->{"_new_Exon$i"});

  my $crick = 1;

  if ($self->{'_strand'} eq 'C') {
     $crick = -1;
  }

  $stop = $self->{'_new_start'} + $crick *($stop - 1);

  if ($stop ne $self->{'_new_stop'}) {
     $error .= "Subfeatures do not cover whole feature region";
  }

  return $error;

}
########################################################################
sub checkIfSameChromosome{
########################################################################
  my ($self, $otherSubFeatureObj) = @_;

  my $chr = $self->{'_chr'};

  my $other_chr = $otherSubFeatureObj->{'_chr'};


  if ($chr != $other_chr) {

     $self->err_report("Two features are not on the same chromosome");
 
  }

  return 1;

}


########################################################################
sub checkIfNextToEachOtherFeatures {
########################################################################
  my ($self, $otherSubFeatureObj) = @_;

  my $coord1 = $self->{'_start'};
  my $coord2 = $otherSubFeatureObj->{'_start'};


  my $count = Feature->GetNumOfFeaturesBetween2StartCoord(dbh=>$dbh,
                                             chr=>$self->{'_chr'},
                                             coord1=>$coord1,
                                             coord2=>$coord2,
                                             strand=>$self->{'_strand'}); 

  if ($count != 0) {
     $self->err_report("Subfeature must be next to each other - there are $count subfeatures between $coord1 and $coord2");
     exit;
  }
}

########################################################################
sub getNewStart {
########################################################################

  my $self = shift;
 
  return $self->{"_new_start"};
}


########################################################################
sub getNewStop {
########################################################################

  my $self = shift;
 
  return $self->{"_new_stop"};
}


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


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


  print hidden(-name=>'new_start',
               -default=>$self->{'_new_start'});

  print hidden(-name=>'new_stop',
               -default=>$self->{'_new_stop'});

  my $i = 1;
  while ($self->{"_new_Exon$i"}) {
    my $value = $self->{"_new_Exon$i"};

    param(-name=>"Exon$i",-value=>$value);

    print hidden(-name=>"Exon$i",
                 -default=>$value);
    $i++;
  }


  my $i = 1;
  while ($self->{"_new_Intron$i"}) {
    my $value = $self->{"_new_Intron$i"};

    param(-name=>"Intron$i",-value=>$value);

    print hidden(-name=>"Intron$i",
                 -default=>$value);
    $i++;
  }

}


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

  my $subFeatureParam;

  my $i = 1;
  while ($self->{"_new_Exon$i"}) {
    if ($i == '1') {
      $subFeatureParam .= "Exon$i=" . $self->{"_new_Exon$i"};
    } else {
      $subFeatureParam .= "&" .  "Exon$i=" . $self->{"_new_Exon$i"};
    }
    $i++;
  } 

  $i = 1;
  while ($self->{"_new_Intron$i"}) {
    $subFeatureParam .= "&" . "Intron$i=" . $self->{"_new_Intron$i"};

    $i++;
  }

  return $subFeatureParam; 
}


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

    #&printStartPage($self->database, $self->title, $self->help);
   
    print b($err);
    
    &printEndPage;

    $dbh->disconnect;
    exit;
}


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



















