# -*- cperl -*-
package Celaenito::IndexerManager;
use strict;
use warnings;
use POE::Session;
use POE::Kernel;
use Celaenito::Logger;
use Celaenito::HyperEstraier;
use Celaenito::Indexer;
use Celaenito::DB;
use Hash::Util qw(lock_keys);
use UNIVERSAL;
use constant CHECK_INTERVAL => 15; # 何秒毎に Indexer を起動するか
use constant ALIAS => 'indexmgr';

sub run {
    defined EST or return;
    
    my $class = shift;
    my $this = bless {} => $class;

    $this->{indexer} = undef; # POE::Session<Indexer>

    lock_keys %$this;

    POE::Session->create(
        heap => $this,
        inline_states => {
            _start     => \&_start_handler,
            _stop      => \&_stop_handler,
            _child     => \&_child_handler,
            shutdown   => \&_shutdown_handler,
            check      => \&_check_handler,
            _signal_stop => sub {
                $_[KERNEL]->sig_handled;
                $_[KERNEL]->yield('shutdown');
            },
        },
       );
}

sub _start_handler {
    $_[KERNEL]->alias_set(ALIAS);
    $_[KERNEL]->delay('check', CHECK_INTERVAL);
    foreach (qw[HUP INT QUIT ABRT TERM]) {
        $_[KERNEL]->sig($_ => '_signal_stop');
    }

    logdebug sprintf(
        'will start indexer every %d seconds.', CHECK_INTERVAL);
}

sub _shutdown_handler {
    my $this = $_[HEAP];
    logdebug "Shutdown time has arrived. Telling indexer to stop...";

    $_[KERNEL]->alias_remove(ALIAS);
    $_[KERNEL]->delay('check');

    if ($_ = $this->{indexer}) {
        $_[KERNEL]->post($_ => 'shutdown');
    }
}

sub _stop_handler {
    logdebug 'STOPPED.';
}

sub _child_handler {
    my ($this, $event, $child_session) = @_[HEAP, ARG0, ARG1];
    my $child = $child_session->get_heap;
    
    if ($event eq 'lose') {
        if (UNIVERSAL::isa($child => 'Celaenito::Indexer')) {
            #logdebug "Indexer stopped.";
            $this->{indexer} = undef;
        }
    }
}

sub _check_handler {
    my $this = $_[HEAP];

    if (not $this->{indexer}) {
        #logdebug 'It is the time to start indexer.';

        $this->{indexer} = Celaenito::Indexer->run();
    }

    $_[KERNEL]->delay('check', CHECK_INTERVAL);
}

1;
