###########################################
package Plugger;
###########################################
use strict; use warnings;

use Module::Pluggable 
  require     => 1,
  search_path => [qw(Plugger)];

our %DISPATCH = ();
our %MEM      = ();

###########################################
sub new {
###########################################
    my($class) = @_;

    bless my $self = {}, $class;

    return $self;
}

###########################################
sub init {
###########################################
    my($self) = @_;

    $_->init($self) for $self->plugins();
}

sub mem { return \%MEM; }

###########################################
sub parse {
###########################################
    my($self, $string) = @_;

    for(sort keys %DISPATCH) {
        $DISPATCH{$_}->{start}->($self) if 
            $DISPATCH{$_}->{start};
    }

    for(split /\n/, $string) {

        s/#.*//;
        next if /^\s*$/;
        last if /^__END__/;
        chomp;

        my($cmd, @args) = split ' ', $_;
        
        die "Unknown command: $cmd" unless
            exists $DISPATCH{$cmd};

        $DISPATCH{$cmd}->{process}->($self,
                              $cmd, @args);
    }

    for(sort keys %DISPATCH) {
        $DISPATCH{$_}->{finish}->($self) if 
            $DISPATCH{$_}->{finish};
    }
}

###########################################
sub register_cmd {
###########################################
    my($self, $cmd, $start, 
       $process, $finish) = @_;

    $DISPATCH{$cmd} = {
        start   => $start, 
        process => $process, 
        finish  => $finish,
    };
}

1;
