package Patro::N6;
use strict;
use warnings;

# Patro::N6. Proxy class for REF type references

# we must keep this namespace very clean
use Carp ();

use overload
    '${}' => \&Patro::N6x::deref,
    'nomethod' => \&Patro::LeumJelly::overload_handler,
    '@{}' => sub { Patro::LeumJelly::deref_handler(@_,'@{}') },
    '%{}' => sub { Patro::LeumJelly::deref_handler(@_,'%{}') },
    '&{}' => sub { Patro::LeumJelly::deref_handler(@_,'&{}') },
    ;

# override UNIVERSAL methods
foreach my $umethod (keys %UNIVERSAL::) {
    no strict 'refs';
    next unless defined &{"UNIVERSAL::" . $umethod};
    *{$umethod} = sub {
	my $proxy = shift;
	if (!CORE::ref($proxy)) {
	    $umethod = "UNIVERSAL::" . $umethod;
	    return $umethod->($proxy,@_);
	}
	my $context = defined(wantarray) ? 1 + wantarray : 0;
	no overloading;
	return Patro::LeumJelly::proxy_request( $proxy,
	    { id => $proxy->{id}, topic => 'METHOD', command => $umethod,
	      has_args => @_ > 0, args => [ @_ ], context => $context }, @_ );
    };
}

sub AUTOLOAD {
    my $method = $Patro::N6::AUTOLOAD;
    $method =~ s/.*:://;

    my $self = shift;
    my $has_args = @_ > 0;
    my $args = [ @_ ];

    my $context = defined(wantarray) ? 1 + wantarray : 0;
    no overloading;

    return Patro::LeumJelly::proxy_request( $self, 
	{ id => $self->{id},
	  topic => 'METHOD',
	  command => $method,
	  has_args => $has_args,
	  args => $args,
	  context => $context,
	  _autoload => 1 }, @_ );
}

sub Patro::N6x::deref {
    my $proxy = shift;
    no overloading;
    my $resp = Patro::LeumJelly::proxy_request(
	$proxy,
	{ id => $proxy->{id},
	  topic => 'REF',
	  command => 'deref',
	  has_args => 0, args => [],
	  context => 1 } );
    return \$resp;
}

sub DESTROY {
    my $self = shift;
    no overloading;
    return if $self->{_DESTROY}++;
    my $socket = $self->{socket};
    my $id = $self->{id};
    
    if ($socket) {

	# XXX - shouldn't disconnect on every object destruction,
	# only when all of the wrapped objects associated with a
	# client have been destroyed, or during global
	# destruction

	Patro::LeumJelly::proxy_request( $self,
	    { id => $id,
	      topic => 'META',
	      command => 'disconnect' } );
	close $socket;
    }
}

1;