package Sanger::Graphics::VDrawableContainer;
use strict;
use base qw(Sanger::Graphics::Root);

sub new {
  my ($class, $Container, $Config, $highlights, $strandedness, $spacing) = @_;

  if(!defined $Container) {
    warn qq(Sanger::Graphics::DrawableContainer::new No container defined);
    return;
  }

  if(!defined $Config) {
    warn qq(Sanger::Graphics::DrawableContainer::new No Config object defined);
    return;
  }

  my $self = {
    'vc'        => $Container,
    'glyphsets' => [],
    'config'    => $Config,
    'spacing'   => $spacing || $Config->{'_spacing'} || 20,
  };
  bless($self, $class);

  ########## loop over all the glyphsets the user wants:
  my $tmp = {};
  my @chromosomes = $Container->{'sa'}->chromosomes();
  my $pos = 100000;
  my $row = '';
  my @subsections =
    map { $_->[1] }
    sort { $a->[0] <=> $b->[0] }
    map {
      $Config->get($_, 'on') eq "on" ? [$Config->get($_,'pos')||$pos++,$_] : () ;
    } $Config->subsections;

  foreach my $chr ( @chromosomes ) {
    for my $row (@subsections) {
      ########## create a new glyphset for this row
      my $classname = qq(Bio::EnsEMBL::GlyphSet::).( $Config->get($row, 'manager')||$row );

      next unless $self->dynamic_use( $classname );

      my $GlyphSet;
      eval {
        $GlyphSet = new $classname($Container, $Config, $highlights, 0, { 'chr' => $chr, 'row' => $row } );
      };

      if($@ || !$GlyphSet) {
        my $reason = $@ || "No reason given just returns undef";
        warn "GLYPHSET: glyphset $classname failed : $reason";
      } else {
         $GlyphSet->_init();
         push @{$self->{'glyphsets'}},  $GlyphSet;
      }
    }
  }

  ########## sort out the resulting mess
  my $scalex = $Config->{'_image_height'} / $Config->container_width();
  $Config->{'transform'}->{'scalex'} = $scalex;
  $Config->{'transform'}->{'absolutescalex'} = 1; # $Config->{'_image_height'} / $Config->image_width();
  $Config->{'transform'}->{'translatex'} += $Config->{'_top_margin'};

  ########## go ahead and do all the database work
  my $yoffset = 0;
  my $glyphsets = @{$self->{'glyphsets'}};

## Firstly lets work how many entries to draw per row!
## Then work out the minimum start for each of these rows
## We then shift up all these points up by that many base 
## pairs to close up any gaps
  my $GS = $Config->{'_group_size'} || 1; 
#  warn $GS;
  my $entries_per_row = $Config->{'_columns'} || ( int( ($glyphsets/$GS - 1) / ($Config->{'_rows'} || 1) + 1 ) * $GS ); 
  my $entry_no = 0;
  $Config->{'_max_height'} =  0;
  $Config->{'_max_width'}  =  0;

  my @min   = ();
  my @max   = ();
  my $row_count = 0;
  my $row_index = 0;
  for my $glyphset (@{$self->{'glyphsets'}}) {
    $min[$row_index] = $glyphset->minx() if(!defined $min[$row_index] || $min[$row_index] > $glyphset->minx() );
    unless(++$row_count < $entries_per_row) {
      $row_count = 0;
      $row_index++;
    }
  }
  ## Close up gap!
#  my $translateX = shift @row_min;
  my $translateX = shift @min;
  $Config->{'transform'}->{'translatex'} -= $translateX * $scalex; #$xoffset;
  my $xoffset = -$translateX * $scalex;

  for my $glyphset (@{$self->{'glyphsets'}}) {
    $Config->{'_max_width'} = $xoffset + $Config->image_width();
    ########## set up the label for this strip 
    ########## first we get the max width of label in characters
    my $gw = 0;
    $gw = length($glyphset->label->text()) if(defined $glyphset->label());
    if(defined $glyphset->label2()) {
      my $gw2 = length($glyphset->label2->text());        
      $gw = $gw2 if $gw2>$gw;
    }
    if($gw>0) {
      ########## and convert it to pels
      $gw *= $Config->texthelper->width($glyphset->label->font());
      ########## If the '_label' position is not 'above' move the labels below the image
      my $label_x = $Config->{'_label'} eq 'above' ? 0 : $Config->{'_image_height'};
      $label_x   += 4 - $Config->{'_top_margin'};
      my $label_y = ($glyphset->maxy() + $glyphset->miny() - $gw ) / 2;
      if(defined $glyphset->label()) {
        $glyphset->label->y( $label_y );
        $glyphset->label->x( $label_x / $scalex);            
        $glyphset->label->height($gw);
        $glyphset->push($glyphset->label());
      }
      if(defined $glyphset->label2()) {
        $glyphset->label2->y( $label_y );
        $glyphset->label2->x( ( $label_x + 2 +
                    $Config->texthelper->height($glyphset->label->font()) ) / $scalex);
        $glyphset->label2->height($gw);
        $glyphset->push($glyphset->label2());
      }        
    }
    ########## remove any whitespace at the top of this row
    $Config->{'transform'}->{'translatey'} = -$glyphset->miny() + $spacing/2 + $yoffset;
    $glyphset->transform();
    ########## translate the top of the next row to the bottom of this one
    $yoffset += $glyphset->height() + $spacing;
    $Config->{'_max_height'} = $yoffset + $spacing if( $yoffset + $spacing > $Config->{'_max_height'} );
    unless( ++$entry_no < $entries_per_row ) {
      $entry_no = 0;
      $yoffset = 0;
      my $translateX = shift @min;
      $translateX  ||= 0;
      $xoffset += $Config->image_width() - $translateX * $scalex;
      ## Shift down - and then close up gap!
        $Config->{'transform'}->{'translatex'} += $Config->image_width() - $translateX * $scalex; #$xoffset;
    }
  }

  ########## Store the maximum "width of the image"
  return $self;
}

########## render does clever drawing things
sub render {
  my ($self, $type) = @_;
  ########## build the name/type of render object we want
  my $renderer_type = qq(Bio::EnsEMBL::VRenderer::$type);
  ########## dynamic require of the right type of renderer
  return unless $self->dynamic_use( $renderer_type );

  ########## big, shiny, rendering 'GO' button
  my $renderer = $renderer_type->new(
    $self->{'config'},
    $self->{'vc'},
    $self->{'glyphsets'}
  );
  return $renderer->canvas();
}

sub config {
  my ($self, $Config) = @_;
  $self->{'config'} = $Config if(defined $Config);
  return $self->{'config'};
}

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

#sub dynamic_use {
#  my( $self, $classname ) = @_;
#  my( $parent_namespace, $module ) = $classname =~/^(.*::)(.*?)$/;
#  no strict 'refs';
#  return 1 if $parent_namespace->{$module.'::'}; # return if already used
#  eval "require $classname";
#  if($@) {
#    warn "DrawableContainer: failed to use $classname\nDrawableContainer: $@";
#    return 0;
#  }
#  $classname->import();
#  return 1;
#}

1;

=head1 RELATED MODULES

See also: Sanger::Graphics::GlyphSet Sanger::Graphics::Glyph WebUserConfig

=head1 AUTHOR - Roger Pettett

Email - rmp@sanger.ac.uk

=cut