package Tak::WorldHandle;

use IPC::Open2 ();
use Tak::Router;
use Tak::JSONChannel;
use Tak::ModuleSender;
use Tak::Remote;
use IO::All;
use Moo;

sub Tak::WorldHandle::_local::open2 {
  shift;
  my $pid = IPC::Open2::open2(my $out, my $in, @_)
    or die "Couldn't open2 child: $!";
  return ($in, $out, $pid);
}

has connection => (is => 'ro', required => 1);

sub new_local {
  shift->new(connection => bless({}, 'Tak::WorldHandle::_local'))
}

sub new_remote {
  my ($class, $target) = @_;
  $class->new(connection => do {
    require Net::OpenSSH;
    Net::OpenSSH->new($target);
  });
}

has router => (is => 'lazy');

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

  my ($stdin, $stdout) = $self->connection->open2('perl -');

  $stdin->print(io('maint/mk-fat |')->all, "__END__\n");

  my $channel = Tak::JSONChannel->new(
    read_fh => $stdout, write_fh => $stdin
  );

  my $router = Tak::Router->new(
    channel => $channel
  );

  $router->register(module_sender => Tak::ModuleSender->new);

  return $router;
}

sub remote_for {
  my ($self, $name) = @_;
  Tak::Remote->new(router => $self->router, name => $name);
}

1;
