
my @EVENT_TYPE = qw (JOB SEND RECV MODEM);

my @EVENTS = (
	[qw(JOB_CREATE JOB_SUSPEND JOB_READY JOB_SLEEP JOB_DEAD JOB_PROCESS JOB_REAP JOB_ACTIVE JOB_REJECT JOB_KILL JOB_BLOCKED JOB_DELAYED JOB_ALTERED JOB_TIMEDOUT JOB_PREP_BEGIN JOB_PREP_END)],
	[qw(SEND_BEGIN SEND_CALL SEND_CONNECTED SEND_PAGE SEND_DOC SEND_POLLRCVD SEND_POLLDONE SEND_END SEND_REFORMAT SEND_REQUEUE SEND_DONE)],
	[qw(RECV_BEGIN RECV_START RECV_PAGE RECV_DOC RECV_END)],
	[qw(MODEM_ASSIGN MODEM_RELEASE MODEM_DOWN MODEM_READY MODEM_BUSY MODEM_WEDGED MODEM_INUSE MODEM_DATA_BEGIN MODEM_DATA_END MODEM_VOICE_BEGIN MODEM_VOICE_END MODEM_CID)],
);


sub watch
{
    my $ftp = shift;
    my %hash = @_;

    my %mask = (JOB => 0, SEND => 0, RECV => 0, MODEM => 0);

    foreach my $k (keys %hash)
    {
        printf STDERR "`-> %s\n", $k;
        if ($k eq 'JOB')
        {
            $mask{JOB} |= 0xFFFF;
        } elsif ($k =~ m/^JOB_/)
        {
            for ($i = 0; $i < scalar(@{$EVENTS[0]}); $i++)
            { $mask{JOB} |= 1 << $i if ($k eq $EVENTS[0][$i]); }
        } elsif ($k eq 'SEND')
        {
            $mask{SEND} |= 0xFFFF;
        } elsif ($k =~ m/^SEND_/)
        {
            for ($i = 0; $i < scalar(@{$EVENTS[1]}); $i++)
            { $mask{SEND} |= 1 << $i if ($k eq $EVENTS[1][$i]); }
        } elsif ($k eq 'RECV')
        {
            $mask{RECV} |= 0xFFFF;
        } elsif ($k =~ m/^RECV_/)
        {
            for ($i = 0; $i < scalar(@{$EVENTS[2]}); $i++)
            { $mask{RECV} |= 1 << $i if ($k eq $EVENTS[2][$i]); }
        } elsif ($k eq 'MODEM')
        {
            $mask{MODEM} |= 0xFFFF;
        } elsif ($k =~ m/^MODEM_/)
        {
            for ($i = 0; $i < scalar(@{$EVENTS[3]}); $i++)
            { $mask{MODEM} |= 1 << $i if ($k eq $EVENTS[3][$i]); }
        }
    }

    printf STDERR "MASK: J%04X\n", $mask{JOB};
    printf STDERR "MASK: S%04X\n", $mask{SEND};
    printf STDERR "MASK: R%04X\n", $mask{RECV};
    printf STDERR "MASK: M%04X\n", $mask{MODEM};

    my $trigger_spec = sprintf 'J%04XS%04XR%04XM%04X',
        $mask{JOB}, $mask{SEND}, $mask{RECV}, $mask{MODEM};


    watch_events($ftp, $trigger_spec, %hash);
}

sub watch_events 
{
    my ($ftp, $spec, %hash) = @_;

    delete ${*$ftp}{'net_ftp_port'};
    delete ${*$ftp}{'net_ftp_pasv'};

    my $data = $ftp->_data_cmd('SITE TRIGGER', $spec);

    return unless(defined $data);

    require Net::FTP::A;
    bless $data, "Net::FTP::A"; # Force ASCII mode

    my $databuf = '';
    my $blksize = ${*$ftp}{'net_ftp_blksize'};

    while($data->read($databuf,$blksize)) 
    {
	foreach my $line (split(/\n/,$databuf) )
	{
	    if ($line =~ m/^\d{6} (\d{3}) ([A-Z]+) ([^:]*): (.*)/)
	    {
		my ($e, $tag, $id, $data) = ($1 - 100, $2, $3, $4);
		my $et = $e / 16;
		my $ee = $e % 16;
		
		printf STDERR "EVENT %d[%d:%04X] [$tag $id]: $data\n", $e, $et, (1<<$ee);
		printf STDERR " `-> %s [%s]\n", $EVENTS[$et][$ee], ref($hash{$EVENTS[$et][$ee]});

		# JOB_ and SEND_ events have extra crap in their id part
		$id =~ s/ *\(.*\)// if ($et < 2);

		my $action = $hash{$EVENTS[$et][$ee]} || $hash{$EVENT_TYPE[$et]};

		if ( ref($action) eq 'CODE')
		{
#			printf STDERR "CODE: $action\n";
			$action->($id, $data);
		} elsif (ref($action) eq 'ARRAY' && ref(${$action}[0]) eq 'CODE')
		{
#			printf STDERR "ARRAY: $action\n";
			my ($func, @args) = @{$action};
			my $jobid;
			for (my $i = 0; $i < scalar(@args); $i++)
			{
				if ($args[$i] eq 'ID')
				{
				    $args[$i] = $id;
				} elsif ($args[$i] =~ m/JOB:(.*)/)
				{
				    $jobid = $ftp->quot('JOB', $id) unless $jobid;
				    $args[$i] = $ftp->quot('JPARM', $1) && $ftp->message;
				    chomp $args[$i];
				}
#			        printf STDERR "  * ARG '%s'\n", $args[$i]
			}
			$func->(@args);
		} else
		{
#			printf STDERR "   * DON'T KNOW $action\n";
		}

	    } else
	    {
		print STDERR "************************* --> '" . $line . "'\n";
	    }
	}
    }

    $data->close();
    undef
}

1;
