package DJabberd::Delivery::S2S;
use strict;
use warnings;
use base 'DJabberd::Delivery';

use DJabberd::Queue::ServerOut;
use DJabberd::Log;
our $logger = DJabberd::Log->get_logger;

sub run_after { ("DJabberd::Delivery::Local") }

sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    $self->{cache} = {}; # domain -> DJabberd::Queue::ServerOut
    return $self;
}

sub deliver {
    my ($self, $vhost, $cb, $stanza) = @_;
    die unless $vhost == $self->{vhost}; # sanity check

    # don't do s2s if the vhost doesn't have it enabled
    unless ($vhost->s2s) {
        $cb->declined;
        return;
    }

    my $to = $stanza->to_jid
        or return $cb->declined;

    # don't initiate outgoing connections back to ourself
    my $domain = $to->domain;
    if ($vhost->handles_domain($domain)) {
        return $cb->declined;
    }

    $logger->debug("s2s delivery attempt for $to");

    # FIXME: let get_conn_for_domain return an error code or something
    # which we can then pass along smarter to the callback, so client gets
    # a good error?
    my $out_queue = $self->get_queue_for_domain($domain) or
        return $cb->declined;

    $DJabberd::Stats::counter{deliver_s2s}++;
    $out_queue->queue_stanza($stanza, $cb);
}

sub get_queue_for_domain {
    my ($self, $domain) = @_;
    # TODO: we need to clean this periodically, like when connections timeout or fail
    return $self->{cache}{$domain} ||=
        DJabberd::Queue::ServerOut->new(source => $self,
                                        domain => $domain,
                                        vhost  => $self->{vhost});
}

1;
