#
# The PDL::Graphics::TriD::Window is already partially defined in
# the appropriate gdriver (GL or VRML) items defined here are common
# to both
# 

# A function declaration so indirect object method works when defining $ev
# in new_viewport:
sub PDL::Graphics::TriD::EventHandler::new;

package PDL::Graphics::TriD::Window;
use PDL::Graphics::TriD::ViewPort;
use Data::Dumper;
use strict;

sub new {
  my($arg,$options) = @_;

  print "PDL::Graphics::TriD::Window - calling SUPER::new...\n" if($PDL::debug_trid);
  my $this = $arg->SUPER::new();

  print "PDL::Graphics::TriD::Window - got back $this\n" if($PDL::debug_trid);
  # Make sure the Graphics has been initialized
  $options->{width} = 	300 unless defined $options->{width};
  $options->{height} = 	300 unless defined $options->{height};
  $this->{Width} = $options->{width};
  $this->{Height} = $options->{height};

  print "PDL::Graphics::TriD::Window: calling gdriver....\n" if($PDL::debug_trid);
  $this->{Interactive} = $this->gdriver($options);
  print "PDL::Graphics::TriD::Window: gdriver gave back $this->{Interactive}....\n" if($PDL::debug_trid);

  # set default values
  if($this->{Interactive}){
      print "\tIt's interactive... calling ev_defaults...\n" if($PDL::debug_trid);
	 $this->{Ev} = $this->ev_defaults(); 
      print "\tcalling new_viewport...\n" if($PDL::debug_trid);
	 $this->new_viewport(0,0,$this->{Width},$this->{Height});  
  }else{
	 $this->new_viewport(0,0,1,1);  
  }

  $this->current_viewport(0);

  return($this);
}

#
# adds to all viewports
#
sub add_object {
  my($this,$object) = @_;
#  print "add_object ",ref($this),"\n";

  for(@{$this->{_ViewPorts}}) {
	 $_->add_object($object);
  }
}



sub new_viewport {
  my($this,$x0,$y0,$x1,$y1, $options) = @_;
  my $vp = new PDL::Graphics::TriD::ViewPort($x0,$y0,$x1,$y1);
#
  print "Adding viewport $x0,$y0,$x1,$y1\n" if($PDL::Graphics::TriD::verbose);
  push @{$this->{_ViewPorts}}, $vp;
#

  if($this->{Interactive} ){
	 # set a default controller
	 use PDL::Graphics::TriD::ArcBall;
	 use PDL::Graphics::TriD::SimpleScaler;
	 use PDL::Graphics::TriD::Control3D;
         if (defined($PDL::Graphics::TriD::offline) and $PDL::Graphics::TriD::offline==1 ) {
            eval "use PDL::Graphics::TriD::VRML";  
         } else {
            eval "use PDL::Graphics::TriD::GL";  
         }

	 my $ev = $options->{EHandler};
	 $ev = new PDL::Graphics::TriD::EventHandler($vp) unless defined($ev);
	 my $cont = $options->{Transformer};
	 $cont = new PDL::Graphics::TriD::SimpleController() unless defined($cont);

	 $vp->transformer($cont);
    if(ref($ev)){
		$ev->set_button(0,new PDL::Graphics::TriD::ArcCone(
																			$vp, 0,
																			$cont->{WRotation}));
		$ev->set_button(2,new PDL::Graphics::TriD::SimpleScaler(
																				  $vp,
																				  \$cont->{CDistance}));

		$vp->eventhandler($ev);
	 }
  }
  print "new_viewport: ",ref($vp)," ",$#{$this->{_ViewPorts}},"\n" if($PDL::Graphics::TriD::verbose);

  return $vp;
}

sub resize_viewport {
  my($this,$x0,$y0,$x1,$y1,$vpnum) = @_;
  
  $vpnum = $this->{_CurrentViewPort} unless(defined $vpnum);

  my $vp;
  if(defined($this->{_ViewPorts}[$vpnum])){
	 $vp = $this->{_ViewPorts}[$vpnum]->resize($x0,$y0,$x1,$y1);
  }
  return $vp;

}

sub current_viewport {
  my($this,$num) = @_;

  if(defined $num){
	 if(ref($num)){
		my $cnt=0;
		foreach (@{$this->{_ViewPorts}}){
		  if($num == $_){
			 $this->{_CurrentViewPort} = $cnt;
			 $_->{Active}=1;
		  }elsif(defined $_){
			 $_->{Active}=0;
		  }
		  $cnt++;
		}
	 }else{
		if(defined $this->{_ViewPorts}[$num]){
		  $this->{_CurrentViewPort} = $num;
		  $this->{_ViewPorts}[$num]->{Active}=1;
		}else{
		  print "ERROR: ViewPort $num undefined\n";
		}
	 }
  }
  return $this->{_ViewPorts}[$this->{_CurrentViewPort}];
}


sub viewports {
  my ($this) = shift;
  return $this->{_ViewPorts};
}

sub _vp_num_fromref {
  my ($this,$vp) = @_;

  if(! defined $vp){  
	 $vp = $this->{_CurrentViewPort};
  }elsif(ref($vp)){
	 my $cnt=0;
	 foreach(@{$this->{_ViewPorts}}){
		last if($vp == $_);
		$cnt++;
	 }
	 $vp = $cnt;
  }
  return $vp;
}


sub delete_viewport {
  my($this, $vp) = @_;
  my $cnt;
  if(($cnt=$#{$this->{_ViewPorts}})<= 0){
	 print "WARNING: Cannot delete final viewport - request ignored\n";
	 return;
  }
  $vp = $this->_vp_num_fromref($vp);

  $this->{_ViewPorts}[$vp]->DESTROY();
  
  splice(@{$this->{_ViewPorts}},$vp,1);
  
  if($vp == $cnt){
	 $this->current_viewport($vp-1);
  }
}





sub clear_viewports {
  my($this) = @_;
  foreach(@{$this->{_ViewPorts}}){
	 $_->clear_objects();
  }
}

sub clear_viewport {
  my($this, $vp) = @_;
  my $cnt;

  $vp = $this->_vp_num_fromref($vp);
  $this->{_ViewPorts}[$vp]->clear_objects();

}

sub set_eventhandler {
  my($this,$handler) = @_;

  $this->{EHandler} = $handler;

#  for(@{$this->{_ViewPorts}}) {
#	 $_->eventhandler($handler);
#  }
}

#sub set_transformer {
#  my($this,$transformer) = @_;
#
#  for(@{$this->{_ViewPorts}}) {
#	 $_->transformer($transformer);
#  }
#}


sub AUTOLOAD {
  my ($self,@args)=@_;
  use vars qw($AUTOLOAD);
  my $sub = $AUTOLOAD;
  
# If an unrecognized function is called for window it trys to apply it
# to all of the defined ViewPorts

  $sub =~ s/.*:://;

  print "AUTOLOAD: $sub at ",__FILE__," line ", __LINE__  ,".\n" 
	 if($PDL::Graphics::TriD::verbose);

  print "Window AUTOLOADing '$sub': self=$self, args='".join("','",@args),"'\n" if($PDL::debug_trid);

  if($sub =~ /^gl/ && defined  $self->{_GLObject}){
	 return  $self->{_GLObject}->$sub(@args);
  }


  for(@{$self->{_ViewPorts}}) {
    next unless defined $_;
	 $_->$sub(@args);
  }
}

1;
