package Object::Remote::Role::Connector;

use Module::Runtime qw(use_module);
use Object::Remote::Future;
use Moo::Role;

requires '_open2_for';

has timeout => (is => 'ro', default => sub { { after => 5 } });

sub connect {
  my $self = shift;
  my ($send_to_fh, $receive_from_fh, $child_pid) = $self->_open2_for(@_);
  my $channel = use_module('Object::Remote::ReadChannel')->new(
    fh => $receive_from_fh
  );
  return future {
    my $f = shift;
    $channel->on_line_call(sub {
      if ($_[0] eq "Shere") {
        $f->done(
          use_module('Object::Remote::Connection')->new(
            send_to_fh => $send_to_fh,
            read_channel => $channel,
            child_pid => $child_pid,
          )
        );
      } else {
        $f->fail("Expected Shere from remote but received: $_[0]");
      }
      undef($channel);
    });
    $channel->on_close_call(sub {
      $f->fail("Channel closed without seeing Shere: $_[0]");
      undef($channel);
    });
    Object::Remote->current_loop
                  ->watch_time(
                      %{$self->timeout},
                      code => sub {
                        $f->fail("Connection timed out") unless $f->is_ready;
                        undef($channel);
                      }
                    );
    $f;
  }
}

1;
