package Bio::EnsEMBL::GlyphSet::idhistorytree;

=head1 NAME

EnsEMBL::Web::GlyphSet::idhistorytree;

=head1 SYNOPSIS
=head1 LICENCE

This code is distributed under an Apache style licence:
Please see http://www.ensembl.org/code_licence.html for details

=head1 CONTACT

Bethan Pritchard - bp1@sanger.ac.uk

=cut
use strict;
use vars qw(@ISA $SCORE_COLOURS $COLOURS);
use Bio::EnsEMBL::GlyphSet_simple;
use Bio::EnsEMBL::Feature;
use EnsEMBL::Web::Component;
@ISA = qw(Bio::EnsEMBL::GlyphSet_simple);

my $k;
#warn ("A-0:".localtime());
my %asmbl;

sub render_normal { 
  my ($self) = @_;
  return unless ($self->strand() == 1);
  my $Config = $self->{'config'};  
  my $history_tree = $self->{'container'}; 
  my $a_id = $self->{'config'}->{_object}->stable_id;

  ## Define basic set up variables ##
  my $panel_width = $Config->image_width();
  my ($fontname, $fontsize) = $self->get_font_details('medium');
  my( $fontname_o, $fontsize_o ) = $self->get_font_details( 'label' );
  my @res_o = $self->get_text_width( 0, 'X', '', 'font'=>$fontname_o, 'ptsize' => $fontsize_o );
  my $th_o = $res_o[3];

  my $fontheight = 5;
  my $bg = $Config->get_parameter('bgcolour2') || 'background2';
  ## Variable declaration ##

  my $x = 140;
  my $y = 100;  
  my $working_length = $panel_width -160;
  my (%xc, %yc, @ns);

  ## Define Score colours ##
  my $cmap = $Config->colourmap();
  $SCORE_COLOURS  ={qw(
      0  CCCCCC
     49  FFF400
     50  FFAA00   
     75  FF5600
     90  FF1900  
     97  BB0000
     99  690000
    100  000000
  )};
  for my $k (keys %$SCORE_COLOURS) {
    $cmap->add_hex($SCORE_COLOURS->{$k});
  }
  my $branch_col;   
  ## Set X coordinates ##

  my @releases = sort {$a <=> $b} @{$history_tree->get_release_display_names};
#warn "Releases... @releases";
  my $count = scalar(@releases);
     $count --;
  my $interval = $working_length / $count;
  my $temp_x = 140; 

  my @unique_ids = @{ $history_tree->get_unique_stable_ids };
  my $species = $ENV{'ENSEMBL_SPECIES'};
  my $type =  lc($self->{'config'}->{_object}->type);
  my $param;
  if ($type =~/translation/){
    $param = 'protein'
  } else {
    $param = substr $type, 0, 1;
  }
   ## Set Y coordinates ##
  foreach my $id (@unique_ids) {
    my $param2 = $self->{'config'}->{_object}->type eq 'Translation' ? 'peptide' : lc($self->{'config'}->{_object}->type);
    my $id_l = qq(/$species/idhistoryview?$param2=$id); 
    my $y_coord = $y;
    $yc{$id} = $y_coord;
    $y +=50;

    my $label_href = $self->_url
    ({'action'  => 'Idhistory_Label',
      'label'   => $id,
      'feat_type'    =>  $param2,
      $param    => $id, 
    });
    # label unique stable IDs
    $self->push( $self->Text({
      'x'         => 5,
      'y'         => $y_coord,
      'width'     => 140,
      'height'    => $fontheight,
      'font'      => $fontname,
      'ptsize'    => $fontsize,
      'halign'    => 'left',
      'colour'    => 'blue',
      'text'      =>  $id,
      'href'     =>   $label_href
    }));

    if ($id eq $a_id) { ## Highlight the focus id ##
      $self->unshift( $self->Rect({
        'x'         => -5,
        'y'         => $y_coord - 15,
        'width'     => $panel_width + 20,
        'height'    => 30,
        'colour'    => $bg,
      }));
    }
  }

  foreach my $r (@releases) {
     $xc{$r} = $temp_x;
     $temp_x += $interval;
  }

  my $last_rel = $releases[$count];

  my @events = @{ $history_tree->get_all_StableIdEvents };
  ## Draw Score boxes ##
  my $boxxcoord = $x -90;
  foreach my $sc (sort { $b<=>$a } keys %$SCORE_COLOURS) {
    my $colour = $SCORE_COLOURS->{$sc};  
    my $scorebox = $self->Rect({
      'x'         => $boxxcoord,
      'y'         => 50,
      'width'     => 20,
      'height'    => 10,
      'colour'    => $colour,
    });
    $self->push($scorebox);

    $sc = sprintf("%.2f", $sc/100);
    my $sc_label  = $sc == 0    ? "Unknown" 
                  : $sc <  0.5  ? "<0.50"
		  : $sc == 1    ? $sc
		  :               ">=".$sc
		  ;

    $self->push( $self->Text({
      'x'         => $boxxcoord + 25,
      'y'         => 55,
      'height'    => $fontheight,
      'font'      => $fontname,
      'ptsize'    => $fontsize,
      'halign'    => 'left',
      'colour'    => 'black',
      'text'      => $sc_label,
    }));

    $self->push( $self->Text({
      'x'         => 1,
      'y'         => 55,
      'height'    => $fontheight,
      'font'      => $fontname,
      'ptsize'    => $fontsize,
      'halign'    => 'left',
      'colour'    => 'black',
      'text'      => 'Score',
    }));
    $boxxcoord += 65;
  }

  ## Define nodes Nodes ##
  my @x_c = values (%xc);
  my @sortedx = sort ({$a <=> $b} @x_c);

  foreach my $a_id (@{ $history_tree->get_all_ArchiveStableIds }) {
    my $node_href = $self->_url
      ({'action'   => 'Idhistory_Node',
        'node'     => $a_id->stable_id,
        'db_name'  => $a_id->db_name,
         $param => $a_id->stable_id  });

    # only draw node if the version from the next release is different or if
    # this version links to a different id      
    my $true = 0;
    my $final_rel = 0;
    my $first_rel =$last_rel;

    my ($x, $y) = @{ $history_tree->coords_by_ArchiveStableId($a_id) };
    my $id = $a_id->stable_id;
    my $version = $a_id->version;
    my $arelease = $a_id->release;
#warn ">>>> $id($version/$arelease) $x <<>> $y <<<";
    foreach my $e (@events){
      my $old = $e->old_ArchiveStableId;
      my $new = $e->new_ArchiveStableId;
      next unless ($old && $new);
      if ($new->stable_id eq $id && $new->version == $version){
        my $new_rel = $new->release;
        if ($new_rel >= $final_rel){$final_rel = $new_rel;}            
        if ($new_rel <+ $first_rel){$first_rel = $new_rel;}
      }
      if ($old->stable_id eq $id && $old->version == $version){
        my $old_rel = $old->release;
        if ($old_rel >= $final_rel){$final_rel = $old_rel;}
        if ($old_rel <+ $first_rel){$first_rel = $old_rel;}
      }

      if ($id eq $new->stable_id && $version == $new->version){
        unless ($new->stable_id eq $old->stable_id) {$true =1;}
      }       
      if ($id eq $old->stable_id && $version == $old->version){
        unless ($old->stable_id eq $new->stable_id) {$true =1;}
      }
    }     

    my $xcoord = $sortedx[$x];
    my $ycoord = $yc{$a_id->stable_id};
    my $node_col = $SCORE_COLOURS->{'100'};
    my $node = $self->Rect({
        'x'         => $xcoord,
        'y'         => $ycoord - 1.5,
        'width'     => 3,
        'height'    => 3,
        'colour'    => $node_col,
        'href'     =>  $node_href,
        });
    push (@ns, $node);

    my $nl = $a_id->version;
    my $node_label = $self->Text({
        'x'         => $xcoord,
        'y'         => $ycoord +7,
        'height'    => $fontheight,
        'font'      => $fontname,
        'ptsize'    => $fontsize,
        'halign'    => 'left',
        'colour'    => 'black',
        'text'      => $nl,
        'absolutey' => 1,
        });
    $self->push($node_label);
  }
  ## Draw branches ##
  foreach my $event (@events) {
    my $old = $event->old_ArchiveStableId;
    my $new = $event->new_ArchiveStableId;

    next unless ($old && $new);

    my $old_id = $old->stable_id;
    my $new_id = $new->stable_id;
    my $old_db = $old->db_name;
    my $new_db = $new->db_name;
    my $escore = $event->score;
    my $branch_href = $self->_url
      ({'action'   => 'Idhistory_Branch',
        'old'     => $old_id,
        'new'     => $new_id,
        'old_db'  => $old_db,
        'new_db'  => $new_db,
        'score'   => $escore,
        $param    => $old_id, 
      });
    $escore = $escore * 100;
    my $score_group; 
    if ($escore >= 100) {$score_group = '100' ;}
    elsif ($escore >= 99) {$score_group = '99' ;}
    elsif ($escore >= 97) {$score_group = '97' ;}
    elsif ($escore >= 90) {$score_group = '90' ;}
    elsif ($escore >= 75) {$score_group = '75' ;}
    elsif ($escore >= 50) {$score_group = '50' ;}
    elsif ($escore < 50 and $escore > 0) {$score_group = '49' ;}
    elsif ($escore >=0) {$score_group = '0' ;}
    $branch_col = $SCORE_COLOURS->{$score_group};

    my ($oldx, $oldy) = @{$history_tree->coords_by_ArchiveStableId($old)};
    my ($newx, $newy) = @{$history_tree->coords_by_ArchiveStableId($new)};
    if ($oldy == $newy) {
      # add horizontal branches
      my $y_coord = $yc{$old->stable_id};
      my $x_coord = $sortedx[$oldx];
      my $length = $sortedx[$newx] - $sortedx[$oldx];
      my $xend = $x_coord + $length;
      my $y_end = $y_coord +1;
      my $hbr = $self->Line({
         'x'         => $x_coord + 3.2 ,
         'y'         => $y_coord,
         'height'    => 0,
         'width'     => $length -6.4,
         'colour'    => $branch_col,
         'absolutey' => 1,
           'absolutewidth' => 1,
         'clickwidth' => 2,
         'href'     => $branch_href,
      });
      $self->push($hbr);   
    } elsif ($oldx == $newx) {
      # add vertical branches
      my $y_coord = $yc{$old->stable_id};
      my $x_coord = $sortedx[$oldx] ;
      my $height = $yc{$new->stable_id} - $yc{$old->stable_id};
      my $xend = $x_coord + $height;
      my $y_end = $y_coord +1;
      my $vbr = $self->Line({
         'x'         => $x_coord,
         'y'         => $y_coord,
         'height'    => $height,
         'width'     => 0,
         'width'     => 0.25,
         'colour'    => $branch_col,
         'clickwidth' => 2,
         'href'    => $branch_href,
      });
      $self->push($vbr);
    } else {
      # add diagonal branches
      my $x_coord = $sortedx[$oldx];
      my $y_coord = $yc{$old->stable_id};
      my $x_end = $sortedx[$newx];
      my $y_end = $yc{$new->stable_id};
      my $dbr = $self->Line({
         'x'         => $x_coord,
         'y'         => $y_coord,
         'height'    => $y_end - $y_coord,
         'width'     => $x_end - $x_coord,
         'colour'    => $branch_col,
          'absolutey' => 1,
          'absolutewidth' => 1,
         'clickwidth' => 2,
         'href'    => $branch_href,
      });
      $self->push($dbr);
    }

  }       
  ## Draw the nodes ##
  foreach my $n (@ns){
    $self->push($n);
  } 

  ## Add assembly information ##

  my $asmbl_label = $self->Text({
        'x'         => 5,
       'y'         => $y,
       'height'    => $fontheight,
       'font'      => $fontname,
       'ptsize'    => $fontsize,
       'halign'    => 'left',
       'colour'    => 'black',
       'text'      => "Assembly",
       'absolutey' => 1,
 });

  $self->push($asmbl_label);

  my %archive_info = %{$Config->species_defs->get_config($species, 'ASSEMBLIES')}; 

  my @a_colours = ('contigblue1', 'contigblue2');
  my $i =0;
  my $pix_per_bp = $self->{'config'}->transform()->{'scalex'};
  my $strand = ">";

  foreach my $r (@releases){
    my $tempr = $r; 
    if ($tempr =~/\./){ $tempr=~s/\.\d*//; }
    my $current_r = $archive_info{$tempr}; 
    push @{$asmbl{$current_r}} , $r;
  }
  my %asmbl_seen;

  foreach my $key ( @releases){    
   my $tempr = $key; 
   if ($tempr =~/\./){ $tempr=~s/\.\d*//; }
    my $a = $archive_info{$tempr};
    if (exists $asmbl_seen{$a}){
      next;
    }
    else {
      $asmbl_seen{$a} = $key;    
      my $r = $asmbl{$a};    
      my @sorted = sort @{$r};
      my $size = @sorted;
      my $start = ($xc{$sorted[0]}) + 2;
      my $offset = $interval / 2;
      $start -= $offset;
      my $end = $start + ($interval * $size);
      $end -= 4;
      if ($sorted[0] == $releases[0]){ $start = ($xc{$sorted[0]}) -10; }
      if ($sorted[-1] == $releases[-1]) {$end = $xc{$sorted[-1]} +10; }
      my $length = $end - $start;
      my $colour = $a_colours[$i];     

      my $asmblbox = $self->Rect({
       'x'         => $start,
       'y'         => $y -3,
       'width'     => $length,
       'height'    => 15,
       'colour'    => $colour,
       'title'       => $a,
      });
      $self->push($asmblbox);
      my @res = $self->get_text_width(
       ($end-$start)*$pix_per_bp,
       $strand > 0 ? "$a " : " $a",
       $strand > 0 ? '1' : '0',
       'font'=>$fontname, 'ptsize' => $fontsize
      );

     if( $res[0] ) {
       my $tglyph = $self->Text({
        'x'          => $start +5,
        'height'     => $res[3],
        'width'      => $res[2]/$pix_per_bp,
        'textwidth'  => $res[2],
        'y'          => $y -3,
        'font'       => $fontname,
        'ptsize'     => $fontsize,
        'colour'     => 'white',
        'text'       => $a,
        'absolutey'  => 1,
       });
      $self->push($tglyph);
     }
     if ($i == 1){$i = 0;} 
     else {$i = 1;}
    }
  }
 ## Draw scalebar ##
  $y +=30;
  my $mid_point = ($working_length /2 )+ 140;
  my $label = $self->Text({
      'x'         => $mid_point,
      'y'         => $y + 40,
      'height'    => $fontheight,
      'font'      => $fontname,
      'ptsize'    => $fontsize,
      'halign'    => 'left',
      'colour'    => 'black',
      'text'      => 'Release',
      'absolutey' => 1,
  });

  $self->push($label); 

  my $bar = $self->Line({
      'x'         => $x,
      'y'         => $y,
      'width'     => $working_length,
      'height'    => 0.25,
      'colour'    => 'black',
      'zindex' => 0,
  });
  $self->push($bar);  

  foreach my $r (@releases){
    my $x_coord = $xc{$r};
    my $ty = $y + 8;
   # if ($r == $last_rel){ $x_coord = $working_length - 0.25 + 60};    

    my $tick = $self->Line({
        'x'         => $x_coord,
        'y'         => $y,
        'width'     => 0.25,
        'height'    => -4,
        'colour'    => 'black',
        'zindex' => 1,
    });
    $self->push($tick);

    my $rel_text = $self->Text({
        'x'         => $x_coord -3,
        'y'         => $ty,
        'height'    => $fontheight,
        'font'      => $fontname,
        'ptsize'    => $fontsize,
        'halign'    => 'left',
        'colour'    => 'black',
        'text'      => $r,
        'absolutey' => 1,
    });
    $self->push($rel_text);  

  }
  #warn ("B-0:".localtime());      

  return 1;
}

1;