$^W=1;
use strict;

# sub POE::Kernel::TRACE_EVENTS () {1}
# sub POE::Kernel::TRACE_RETURNS () {1}
use POE::Kernel;

eval {
    Test::Client->spawn($ARGV[0]);
    $poe_kernel->run();
};
warn $@ if $@;

################################################################
package Test::Client;
use strict;

use POE::Component::IKC::Client;
use POE::Component::IKC::Responder;
use POE::Session;

sub DEBUG { 0 }


sub spawn 
{
    my($package, $type)=@_;

    POE::Session->create(
        args=>[$type],
        package_states=>[
            $package=>[qw(_start posting calling callback _stop
                 subscribing subscribed unsubscribed YOW
                 registered)],
        ]
    );

}

sub _start
{
    DEBUG and warn "Client: _start\n";
    my($kernel, $heap, $type)=@_[KERNEL, HEAP, ARG0];

    $kernel->alias_set('Client');
    POE::Component::IKC::Responder->spawn();

    my $rname=$heap->{name}=ucfirst $type;
#    $rname='Inet' if $heap->{name} eq 'Ikc';
    my %args=(name=>"$heap->{name}Client");

    if($type eq 'ikc') {
        $args{serializer}='POE::Component::IKC::Freezer';
#        $kernel->post(IKC=>'monitor', 'Inet'=>{register=>'registered'});
#    } else {
    }
    $kernel->post(IKC=>'monitor', $rname=>{register=>'registered'});


    if($type eq 'unix') {
        $args{unix}=($ENV{TMPDIR}||$ENV{TEMP}||'/tmp').'/IKC-test.pl';
    } else {                    # ikc AND inet
        $args{port}=1338;
    }
    POE::Component::IKC::Client->spawn(%args);
}

sub _stop
{
    DEBUG and warn "Client: _stop\n";
}

sub registered
{
    DEBUG and warn "Client: registered\n";
    my($kernel, $heap)=@_[KERNEL, HEAP];
    $kernel->yield('posting');
}

########################################################
sub posting
{
    DEBUG and warn "Client: posting\n";
    my($kernel, $heap)=@_[KERNEL, HEAP];
    $kernel->post(IKC=>'post', "poe://$heap->{name}/test/posted"=>'posted');

    $kernel->yield('calling');
}


########################################################
sub calling
{
    DEBUG and warn "Client: calling\n";
    my($kernel, $heap)=@_[KERNEL, HEAP];
    $kernel->call( IKC=>'call', 
                    "poe://$heap->{name}/test/called"=>'called',
                    'poe:callback' 
                 );
}

sub callback
{
    DEBUG and warn "Client: callback\n";
    my($kernel, $heap)=@_[KERNEL, HEAP];
    $kernel->yield('subscribing');
}

########################################################
sub subscribing
{
    DEBUG and warn "Client: subscribing ($$)\n";
    my($kernel, $heap)=@_[KERNEL, HEAP];
    $kernel->post(IKC=>'monitor', $heap->{name}=>{
                subscribe=>'subscribed',
                unsubscribe=>'unsubscribed'
            });

    $kernel->post(IKC=>'publish', Client=>[qw(YOW)]);
    $kernel->post(IKC=>'subscribe', "poe://$heap->{name}/test");
}

sub subscribed
{
    DEBUG and warn "Client: subscribed\n";
    my($kernel, $heap)=@_[KERNEL, HEAP];
    # warn "$INC{'POE/Component/IKC/Proxy.pm'}";
    $kernel->post("poe://$heap->{name}/test" => 'method', {type => 'method'});
}

sub YOW
{
    DEBUG and warn "Client: YOW\nClient: unsubscribing\n";
    my($kernel, $heap)=@_[KERNEL, HEAP];    
    $kernel->post(IKC=>'retract', Client=>[qw(YOW)]);
    $kernel->post(IKC=>'unsubscribe', "poe://$heap->{name}/test");
}

sub unsubscribed
{
    DEBUG and warn "Client: unsubscribed\n";
    my($kernel, $heap)=@_[KERNEL, HEAP];
    $kernel->call(IKC=>'post', "poe://$heap->{name}/test/done");
    $kernel->post(IKC=>'shutdown');
}


