#########
# Author: rmp@sanger.ac.uk
# Maintainer: webmaster@sanger.ac.uk
# Created: 2001
#
package Sanger::Graphics::Glyph::Composite;
use strict;
use base qw(Sanger::Graphics::Glyph);

sub push {
  my ($self) = shift;
  $self->_push_unshift('push',@_);
}

sub unshift {
  my ($self) = shift;
  $self->_push_unshift('unshift',@_);
}

sub _push_unshift {    
  my $self      = shift;
  my $direction = shift;
  for my $glyph ( ($direction eq 'push') ? @_ : reverse @_ ) {
    next unless $glyph;

    my $gx = $glyph->x();
    my $gw = $glyph->width();
    my $gy = $glyph->y();
    my $gh = $glyph->height();

    if($glyph->{'absolutewidth'}) {
      $self->{'pixperbp'} ||= $glyph->{'pixperbp'};
      ($gx,$gy) = $glyph->centre();
      $gx      -= $gw/(2 * $self->{'pixperbp'});
      $gy      -= $gw/2;
    }

    #########
    # taint ourselves with absolutewidth
    #
    $self->{'absolutewidth'} ||= $glyph->{'absolutewidth'};

    #########
    # track max and min dimensions
    # DO NOT use "||=" because zero is equivalent to undef and zero need to be kept
    #
    $self->{'x'}      = $gx unless defined $self->{'x'};
    $self->{'y'}      = $gy unless defined $self->{'y'};
    $self->{'width'}  = $gw unless defined $self->{'width'};
    $self->{'height'} = $gh unless defined $self->{'height'};

    #########
    # x
    #
    if($gx < $self->{'x'}) {
      my $offset        = $self->{'x'} - $gx;
      $self->{'x'}      = $gx;
      $self->{'width'} += $offset;
      #########
      # if the new glyph is set outside LHS boundary, then the composite stretches
      # and all glyphs already inside need to be offset by the difference
      #
      for my $offset_glyph (@{$self->{'composite'}}) {
	$offset_glyph->x($offset_glyph->x() + $offset);
      }
    }

    if(($gx + $gw) > ($self->x() + $self->width())) {
      #########
      # x unchanged
      #
      $self->{'width'} = $gx + $gw - $self->{'x'};
    }

    #########
    # y
    #
    if($gy < $self->y()) {
      my $offset         = $self->{'y'} - $gy;
      $self->{'y'}       = $gy;
      $self->{'height'} += $offset;
      #########
      # if the new glyph is set outside TOP boundary, then the composite stretches
      # and all glyphs already inside need to be offset by the difference
      #
      for my $offset_glyph (@{$self->{'composite'}}) {
	$offset_glyph->y($offset_glyph->y() + $offset);
      }
    }
    if(($gy + $gh) > ($self->{'y'} + $self->{'height'})) {
      #########
      # y unchanged
      #
      $self->{'height'} = $gy + $gh - $self->{'y'};
    }

    #########
    # make the glyph coords relative to the composite container
    # NOTE: watch out for this if you're creating glyphsets! - don't do this twice
    #
    unless($glyph->{'absolutex'}) {
      if($glyph->{'absolutewidth'}) {
	$glyph->{'x'} = $gx - $self->{'x'}+$gw/(2 * $self->{'pixperbp'});
      } else {
	$glyph->x($gx - $self->{'x'});
      }
    }

    unless($glyph->{'absolutey'}) {
      $glyph->y($gy - $self->{'y'});
    }

    if($glyph->{'absoluteheight'}) {
      $glyph->{'y'} = $gy - $self->{'y'}+ $gh/2;
    }

    if($direction eq 'push') {
      CORE::push @{$self->{'composite'}}, $glyph;
    } else {
      CORE::unshift @{$self->{'composite'}}, $glyph;
    }
  }
}

sub first {
  my ($self) = @_;
  return if(!defined $self->{'composite'});
  return @{$self->{'composite'}}[0];
}

sub last {
  my ($self) = @_;
  return if(!defined $self->{'composite'});
  my $len = scalar @{$self->{'composite'}};
  return undef if($len == 0);
  return @{$self->{'composite'}}[$len - 1];
}

sub glyphs {
  my ($self) = @_;
  return @{$self->{'composite'}};
}

sub transform {
  my ($self, $transform_ref) = @_;
  $self->SUPER::transform($transform_ref);
  for my $sg (@{$self->{'composite'}}) {
    my %tmp_transform = %{$transform_ref};
    $tmp_transform{'translatex'} = $self->pixelx();
    $tmp_transform{'translatey'} = $self->pixely();
    $sg->transform(\%tmp_transform);
  }
}

1;