package MooseX::JobControl::Engine::POE;
use strict;
use Moose;
use Moose::Util::TypeConstraints;
use MooseX::AttributeHelpers;
use MooseX::LogDispatch;
use POE;

extends qw(MooseX::JobControl::Engine);

has session => (
    isa      => 'POE::Session',
    is       => 'ro',
    required => 1,
    default  => sub {
        POE::Session->create(
            object_states => [
                $_[0] => [
                    qw(
                      _start
                      check_queue
                      start_job
                      _stop
                      )
                ],
            ],
        );
    },
);

#
# Methods
#

sub yield {
    my $self = shift;
    $poe_kernel->post( $self->session => @_ );
}

sub call {
    my $self = shift;
    return $poe_kernel->call( $self->session => @_ );
}

sub run {
    my ($self) = @_;
    $self->yield('check_queue');
    $poe_kernel->run;
}

#
# Engine Events
#

sub _start {
    my ($self) = @_;
    $self->notify_observers('starting_engine');
}

sub _stop {
    my ($self) = @_;
    $self->notify_observers('stopping_engine');
}

before 'check_queue' => sub { (shift)->notify_observers('check_queue') };

sub check_queue {
    my ($self) = @_;
    if ( $self->has_jobs ) {
        if ( $self->check_worker_threashold ) {
            $self->yield('check_queue');
            return;
        }
        $self->yield('start_job');
        return;
    }
    $self->yield('_stop');
}

sub start_job {
    my ($self) = @_;
    my $job    = $self->next_job;
    my $run    = $job->can('run');
    $self->add_process( $self->spawn( $job->command, $job->args ) );
    $self->yield('check_queue');
}

no Moose;  # unimport Moose's keywords so they won't accidentally become methods
1;         # Magic true value required at end of module
__END__
