#! /usr/bin/env perl

use strict;
use utf8;
use Hydra::Event::BuildFinished;
use Hydra::Helper::AddBuilds;
use Hydra::Helper::Nix;
use Hydra::Plugin;
use Hydra::PostgresListener;
use Getopt::Long;

STDERR->autoflush(1);
STDOUT->autoflush(1);
binmode STDERR, ":encoding(utf8)";

my $queued_only;

GetOptions(
    "queued-only" => \$queued_only
) or exit 1;

my $config = getHydraConfig();

my $db = Hydra::Model::DB->new();

my @plugins = Hydra::Plugin->instantiate(db => $db, config => $config);

my $dbh = $db->storage->dbh;

my $listener = Hydra::PostgresListener->new($dbh);
$listener->subscribe("build_started");
$listener->subscribe("build_finished");
$listener->subscribe("step_finished");

sub runPluginsForEvent {
    my ($event) = @_;

    foreach my $plugin (@plugins) {
        eval {
            $event->execute($db, $plugin);
            1;
        } or do {
            print STDERR "error running $event->{'channel_name'} hooks: $@\n";
        }
    }
}

# Process builds that finished while hydra-notify wasn't running.
for my $build ($db->resultset('Builds')->search(
                   { notificationpendingsince => { '!=', undef } }))
{
    print STDERR "sending notifications for build $build->id...\n";


    my $event = Hydra::Event::BuildFinished->new($build->id);
    runPluginsForEvent($event);
}


# Process incoming notifications.
while (!$queued_only) {
    my $messages = $listener->block_for_messages();
    while (my $message = $messages->()) {

        my $channelName = $message->{"channel"};
        my $pid = $message->{"pid"};
        my $payload = $message->{"payload"};

        eval {
            my $event = Hydra::Event::new_event($channelName, $message->{"payload"});
            runPluginsForEvent($event);

            1;
        } or do {
            print STDERR "error processing message '$payload' on channel '$channelName': $@\n";
        }
    }
}