The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
use strict;
use Test::More;

#plan skip_all => 'MSWin32 does not have a proper fork()' if $^O eq 'MSWin32';
BEGIN {
   eval { require POE::Component::Client::HTTP; };
   plan skip_all => 'POE::Component::Client::HTTP is required for this test' if $@;
}

plan tests => 6;

use HTTP::Request;
use POE;
use POE::Kernel;
#sub POE::Component::Server::SimpleHTTP::DEBUG () { 1 }
use POE::Component::Server::SimpleHTTP;

my $PORT = 2080;
my $IP = "localhost";

our %STREAMS;

####################################################################
POE::Component::Server::SimpleHTTP->new(
                'ALIAS'         =>      'HTTPD',
                'ADDRESS'       =>      "$IP",
                'PORT'          =>      $PORT,
                'HOSTNAME'      =>      'pocosimpletest.com',
                'HANDLERS'      =>      [
               		{
               			'DIR'		=>	'.*',
               			'SESSION'	=>	'HTTP_GET',
               			'EVENT'		=>	'GOT_MAIN',
               		},
                ],
		SETUPHANDLER => { SESSION => 'HTTP_GET', EVENT => '_tests', },
);
# Create our own session to receive events from SimpleHTTP
POE::Component::Client::HTTP->spawn(
         Agent     => 'TestAgent',
         Alias     => 'ua',
         Protocol  => 'HTTP/1.1', 
         From      => 'test@tester',
         Streaming => 100,
	 Proxy     => q{},
);

POE::Session->create(
                inline_states => {
                        '_start'        => sub {   
                           $_[KERNEL]->alias_set( 'HTTP_GET' );
                           $_[KERNEL]->yield('keepalive');
			   return;
                        },
			'_tests'     => \&_tests,
                  	'GOT_MAIN'   =>	\&GOT_MAIN,
                  	'GOT_STREAM' =>	\&GOT_STREAM,
		        keepalive    => \&keepalive,
			response     => \&response,
			'_shutdown'  => \&_shutdown,
                        'on_close'   => \&on_close,
                },   
);
    
$poe_kernel->run();

is( 0+keys %STREAMS, 0, "No open streams" );
exit 0;

sub GOT_MAIN {
   # ARG0 = HTTP::Request object, ARG1 = HTTP::Response object, ARG2 = the DIR that matched
   my( $kernel, $heap, $request, $response, $dirmatch ) = @_[KERNEL, HEAP, ARG0 .. ARG2 ];
    
   # Do our stuff to HTTP::Response
   $response->code( 200 );

   $response->content_type("text/plain");
   
   print "# GOT_MAIN \n";
   # sets the response as streamed within our session with the stream event
   $response->stream(
      session     => 'HTTP_GET',
      event       => 'GOT_STREAM'
   );   

   $heap->{'count'} ||= 0;

   my $c = $response->connection;
   $STREAMS{ $c->ID }=1;

   $_[KERNEL]->call( $_[SENDER], 'SETCLOSEHANDLER', $c, 'on_close', $c->ID );
    
    # We are done!
   $kernel->yield('GOT_STREAM', $response);
   return;
}

sub GOT_STREAM {
   my ( $kernel, $heap, $response ) = @_[KERNEL, HEAP, ARG0];

   # lets go on streaming ...
   if ($heap->{'count'} <= 2) {
      my $text = "Hello World ".$heap->{'count'}." \n";
      #print "send ".$text."\n";
      $response->content($text);
      
      $heap->{'count'}++;
      POE::Kernel->post('HTTPD', 'STREAM', $response);
   }
   else {
      $STREAMS{ $response->connection->ID }--;

      POE::Kernel->post('HTTPD', 'CLOSE', $response );
   }
   return;
}

sub keepalive { 
   my $heap  = $_[HEAP];

   $_[KERNEL]->delay_set('keepalive', 1);
   return;
}

sub _shutdown {
  $poe_kernel->alarm_remove_all();
  $poe_kernel->alias_remove( 'HTTP_GET' );
  $poe_kernel->post( 'ua', 'shutdown' );
  $poe_kernel->post( 'HTTPD', 'SHUTDOWN' );
  return;
}

sub _tests {
      my ( $kernel, $heap, $session ) = @_[KERNEL, HEAP, SESSION ];
      $heap->{'client_count'} = 0;
   
      my $request = HTTP::Request->new(GET => "http://$IP:$PORT/");
      
      diag('Test a stream of 3 helloworlds ..');
      POE::Kernel->post('ua', 'request', 'response', $request);
      return;
}
   
sub response {
      my ( $kernel, $heap, $session, $request_packet, $response_packet ) 
         = @_[KERNEL, HEAP, SESSION, ARG0, ARG1];
   
      my $return;
   
      # HTTP::Request
      my $request  = $request_packet->[0];
      my $response = $response_packet->[0];
      
      # the PoCoClientHTTP sends the first chunk in the content
      # of the http response
      #if ($heap->{'count'} == 1) {
      #   my $data = $response->content;
      #   chomp($data);
#print $data."\n";
       #  ok($data =~ /Hello World 0/, "First one as response content received");
      #}
      
      # then all streamed data in the second element of the response
      # array ...
      my ($resp, $data) = @$response_packet;
      return unless $data;
      chomp($data);
      foreach my $hello ( split /\n/, $data ) {
         ok($hello =~ /Hello World/, "Received a hello");
         $heap->{'client_count'}++;
      }
      if ($heap->{'client_count'} == 3) {
         is($heap->{'client_count'}, 3, "Got 3 streamed helloworlds ... all good :)");
	 $kernel->yield( '_shutdown' );
	 return;
      }
      return;
}

sub on_close {
    my $wid  = $_[ARG0];
    is( $STREAMS{$wid}, 0, "on_close comes after CLOSE" );
    delete $STREAMS{ $wid } if $STREAMS{ $wid } == 0;
}