#
# Module Generated by Template::Tiny on Sun Mar  3 10:14:01 UTC 2019
#

package ZMQ::FFI::ZMQ2::Context;
$ZMQ::FFI::ZMQ2::Context::VERSION = '1.15';
use FFI::Platypus;
use ZMQ::FFI::Util qw(zmq_soname current_tid);
use ZMQ::FFI::Constants qw(:all);
use ZMQ::FFI::ZMQ2::Socket;
use ZMQ::FFI::ZMQ2::Raw;
use ZMQ::FFI::Custom::Raw;
use Try::Tiny;
use Scalar::Util qw(weaken);

use Moo;
use namespace::clean;

with qw(
    ZMQ::FFI::ContextRole
    ZMQ::FFI::ErrorHelper
    ZMQ::FFI::Versioner
);

my $FFI_LOADED;

sub BUILD {
    my ($self) = @_;

    unless ($FFI_LOADED) {
        ZMQ::FFI::Custom::Raw::load($self->soname);
        ZMQ::FFI::ZMQ2::Raw::load($self->soname);
        $FFI_LOADED = 1;
    }

    $self->init()
}


has '+threads' => (
    default => 1,
);

sub init {
    my ($self) = @_;

    if ($self->has_max_sockets) {
        $self->bad_version(
            $self->verstr,
            'max_sockets option not available in zmq 2.x',
            'use_die',
        )
    }

    try {
        $self->context_ptr( zmq_init($self->threads) );
        $self->check_null('zmq_init', $self->context_ptr);
    }
    catch {
        $self->context_ptr(-1);
        die $_;
    };
}

sub get {
    my ($self) = @_;

    $self->bad_version(
        $self->verstr,
        "getting ctx options not available in zmq 2.x"
    );
}

sub set {
    my ($self) = @_;

    $self->bad_version(
        $self->verstr,
        "setting ctx options not available in zmq 2.x"
    );
}

sub socket {
    my ($self, $type) = @_;

    my $socket;

    try {
        my $socket_ptr = zmq_socket($self->context_ptr, $type);

        $self->check_null('zmq_socket', $socket_ptr);

        $socket = ZMQ::FFI::ZMQ2::Socket->new(
            socket_ptr   => $socket_ptr,
            context      => $self, # this will become a weak ref
            type         => $type,
            soname       => $self->soname,
        );
    }
    catch {
        die $_;
    };

    # add the socket to the socket hash
    $self->_add_socket($socket);

    return $socket;
}

sub proxy {
    my ($self, $frontend, $backend, $capture) = @_;

    if ($capture){
        $self->bad_version(
            $self->verstr,
            "capture socket not supported in zmq 2.x"
        );
    }

    $self->check_error(
        'zmq_device',
        zmq_device(ZMQ_STREAMER, $frontend->socket_ptr, $backend->socket_ptr)
    );
}

sub device {
    my ($self, $type, $frontend, $backend) = @_;

    $self->check_error(
        'zmq_device',
        zmq_device($type, $frontend->socket_ptr, $backend->socket_ptr)
    );
}

sub destroy {
    my ($self) = @_;

    return if $self->context_ptr == -1;

    # don't try to cleanup context cloned from another thread
    return unless $self->_tid == current_tid();

    # don't try to cleanup context copied from another process (fork)
    return unless $self->_pid == $$;

    $self->check_error(
        'zmq_term',
        zmq_term($self->context_ptr)
    );

    $self->context_ptr(-1);
}

sub curve_keypair {
    my ($self) = @_;
    $self->bad_version(
        $self->verstr,
       "curve_keypair not available in < zmq 4.x"
    );
}

sub has_capability {
    my ($self) = @_;
    $self->bad_version(
        $self->verstr,
       "has_capability not available in < zmq 4.1"
    );
}


sub _add_socket {
    my ($self, $socket) = @_;
    weaken($self->sockets->{$socket} = $socket);
}

sub _remove_socket {
    my ($self, $socket) = @_;
    delete($self->sockets->{$socket});
}

sub DEMOLISH {
    my ($self) = @_;

    return if $self->context_ptr == -1;

    # check defined to guard against
    # undef objects during global destruction
    if (defined $self->sockets) {
        for my $socket_k (keys %{$self->sockets}) {
            my $socket = $self->_remove_socket($socket_k);
            $socket->close()
                if defined $socket && $socket->socket_ptr != -1;
        }
    }

    $self->destroy();
}

1;

# vim:ft=perl

__END__

=pod

=encoding UTF-8

=head1 NAME

ZMQ::FFI::ZMQ2::Context

=head1 VERSION

version 1.15

=head1 AUTHOR

Dylan Cali <calid1984@gmail.com>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2019 by Dylan Cali.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
