#!/usr/bin/env perl

use strict;
use warnings;
use File::Spec;

use Hermes;
use MIO::TCP;
use Poros::Query;
use Vulcan::OptConf;

use constant PORT => 12345;

$| ++;

$Vulcan::OptConf::THIS = 'poros';
$Vulcan::OptConf::ARGC = -1;
@Vulcan::OptConf::CONF = qw( no_ignore_case pass_through ); 

=head1 SYNOPSIS

 $0 -r range [--user username] [--timeout seconds] [--max number] cmd ..

=cut
my $option = Vulcan::OptConf->load();
my %o = $option->get( qw( range=s user=s timeout=i max=i ) )->dump();

$option->assert( 'range' );

my $code = shift;
my $port = delete $o{port} || PORT;
my %query = ( code => $code, logname => operator(), argv => argv( $code ) );

$query{user} = delete $o{user} if $o{user};

my $range = Hermes->new( $option->dump( 'range' ) );
my %result = MIO::TCP
    ->new( map { join ':', $_, $port } $range->load( delete $o{range} )->list )
    ->run( %o, input => Poros::Query->dump( \%query ) );

my %mesg;
while ( my ( $type, $mesg ) = each %result )
{
    while ( my ( $mesg, $node ) = each %$mesg )
    {
        map { $_ =~ s/:$port$// } @$node;

        $mesg =~ s/--- \d+\n$//;
        $node = $range->load( $node )->dump();
        $mesg{$type}{$node} = YAML::XS::Load( $mesg ) if $mesg;
    }
}

YAML::XS::DumpFile \*STDERR, \%mesg if %mesg;
exit 0;

sub operator
{
    my $name = `logname`; chop $name; return $name;
}

sub argv
{
    my $code = File::Spec->join( $o{argv}, shift );
    return -f $code && ( $code = do $code ) && ref $code eq 'CODE'
        ? &$code( @ARGV ) : \@ARGV;
}
