package Bio::EnsEMBL::VRenderer::gif;

use strict;
use GD;
use base qw(Bio::EnsEMBL::VRenderer);

sub init_canvas {
  my ($self, $config, $im_height, $im_width) = @_;
  my $canvas = new GD::Image($im_width, $im_height);
  $canvas->colorAllocate($config->colourmap()->rgb_by_name( $config->bgcolor ));
  $self->canvas($canvas);
}

sub add_canvas_frame {
  my ($self, $config, $im_height, $im_width) = @_;
  return;
}

sub canvas {
  my ($self, $canvas) = @_;
  if(defined $canvas) {
    $self->{'canvas'} = $canvas;
  } else {
    return $self->{'canvas'}->gif();
  }
}

#########
# colour caching routine.
# GD can only store 256 colours, so need to cache the ones we colorAllocate. (Doh!)
# 
sub colour {
  my ($self, $id) = @_;
  $id           ||= "black";
  my $colour      = $self->{'_GDColourCache'}->{$id} || $self->{'canvas'}->colorAllocate($self->{'colourmap'}->rgb_by_name($id));

  $self->{'_GDColourCache'}->{$id} = $colour;
  return $colour;
}
sub render_Rect {
  my ($self, $glyph) = @_;
  my $canvas = $self->{'canvas'};
  my $gcolour       = $glyph->colour();
  my $gbordercolour = $glyph->bordercolour();
  # (avc)
  # this is a no-op to let us define transparent glyphs
  # and which can still have an imagemap area BUT make
  # sure it is smaller than the carrent largest glyph in
  # this glyphset because its height is not recorded!
  if ($gcolour eq 'transparent') {
    return;
  }
  my $bordercolour  = $self->colour($gbordercolour);
  my $colour        = $self->colour($gcolour);
  my $x1 = $glyph->pixelx();
  my $x2 = $glyph->pixelx() + $glyph->pixelwidth();
  my $y1 = $glyph->pixely();
  my $y2 = $glyph->pixely() + $glyph->pixelheight();
  $canvas->filledRectangle($y1, $x1, $y2, $x2, $colour) if(defined $gcolour);
  $canvas->rectangle($y1, $x1, $y2, $x2, $bordercolour) if(defined $gbordercolour);
}

sub render_Text {
  my ($self, $glyph) = @_;
  my $colour         = $self->colour($glyph->colour());
  #########
  # BAH! HORRIBLE STINKY STUFF!
  # I'd take GD voodoo calls any day
  #
  if($glyph->font() eq "Tiny") {
    $self->{'canvas'}->string(gdTinyFont, $glyph->pixely(), $glyph->pixelx(), $glyph->text(), $colour);
  } elsif($glyph->font() eq "Small") {
    $self->{'canvas'}->string(gdSmallFont, $glyph->pixely(), $glyph->pixelx(), $glyph->text(), $colour);
  } elsif($glyph->font() eq "MediumBold") {
    $self->{'canvas'}->string(gdMediumBoldFont, $glyph->pixely(), $glyph->pixelx(), $glyph->text(), $colour);
  } elsif($glyph->font() eq "Large") {
    $self->{'canvas'}->string(gdLargeFont, $glyph->pixely(), $glyph->pixelx(), $glyph->text(), $colour);
  } elsif($glyph->font() eq "Giant") {
    $self->{'canvas'}->string(gdGiantFont, $glyph->pixely(), $glyph->pixelx(), $glyph->text(), $colour);
  }
}

sub render_Circle {
}

sub render_Ellipse {
}

sub render_Space {
}

sub render_Intron {
  my ($self, $glyph) = @_;
  my $colour = $self->colour($glyph->colour());
  my ($xstart, $xmiddle, $xend, $ystart, $ymiddle, $yend, $strand);
  #########
  # todo: check rotation conditions
  #
  $strand  = $glyph->strand();
  $xstart  = $glyph->pixelx();
  $xend    = $glyph->pixelx() + $glyph->pixelwidth();
  $xmiddle = $glyph->pixelx() + int($glyph->pixelwidth() / 2);
  $ystart  = $glyph->pixely() + int($glyph->pixelheight() / 2);
  $yend    = $ystart;
  $ymiddle = ($strand == 1)?$glyph->pixely():($glyph->pixely()+$glyph->pixelheight());
  $self->{'canvas'}->line($xstart, $ystart, $xmiddle, $ymiddle, $colour);
  $self->{'canvas'}->line($xmiddle, $ymiddle, $xend, $yend, $colour);
}

sub render_Line {
  my ($self, $glyph) = @_;
  my $colour = $self->colour($glyph->colour());
  my $x1     = $glyph->pixelx() + 0;
  my $y1     = $glyph->pixely() + 0;
  my $x2     = $x1 + $glyph->pixelwidth();
  my $y2     = $y1 + $glyph->pixelheight();
  if(defined $glyph->dotted()) {
    $self->{'canvas'}->dashedLine($y1, $x1, $y2, $x2, $colour);
  } else {
    $self->{'canvas'}->line($y1, $x1, $y2, $x2, $colour);
  }
}

sub render_Poly {
  my ($self, $glyph) = @_;
  my $bordercolour = $self->colour($glyph->bordercolour());
  my $colour       = $self->colour($glyph->colour());
  my $poly = new GD::Polygon;
  return unless(defined $glyph->pixelpoints());
  my @points = @{$glyph->pixelpoints()};
  my $pairs_of_points = (scalar @points)/ 2;
  for(my $i=0;$i<$pairs_of_points;$i++) {
    my $x = shift @points;
    my $y = shift @points;
    $poly->addPt($y,$x);
  }
  if(defined $colour) {
    $self->{'canvas'}->filledPolygon($poly, $colour);
  } else {
    $self->{'canvas'}->polygon($poly, $bordercolour);
  }
}

sub render_Composite {
  my ($self, $glyph) = @_;
  #########
  # draw & colour the fill area if specified
  #
  $self->render_Rect($glyph) if(defined $glyph->colour());
  #########
  # now loop through $glyph's children
  #
  $self->SUPER::render_Composite($glyph);
  #########
  # draw & colour the bounding area if specified
  #
  $glyph->{'colour'} = undef;
  $self->render_Rect($glyph) if(defined $glyph->bordercolour());
}

1;