#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;
use Getopt::Long;
use Config::General;
use Params::Validate qw(:all);

use FindBin qw($RealBin);
use lib "$RealBin/../lib";

use perfSONAR_PS::NPToolkit::Services::ServicesMap qw(get_service_object);

my ( $status, $res );

my $default_config             = "/opt/perfsonar_ps/toolkit/etc/service_watcher.conf";
my $default_logger_config      = "/opt/perfsonar_ps/toolkit/etc/service_watcher-logger.conf";


my ($LOGGER_CONF, $CONFIG_FILE, $REGULAR_RESTART, $DEBUGFLAG);

$status = GetOptions(
    'config=s'        => \$CONFIG_FILE,
    'logger=s'        => \$LOGGER_CONF,
    'verbose'         => \$DEBUGFLAG,
    'regular_restart' => \$REGULAR_RESTART,
);

$CONFIG_FILE = $default_config unless ($CONFIG_FILE);
$LOGGER_CONF = $default_logger_config unless ($LOGGER_CONF);

unless ($status) {
    print "$0: [--config=/path/to/service-watcher.conf] [--logger=/path/to/service-watcher_logger.conf] [--regular_restart] [--verbose]\n";
    exit 1;
}

my %conf = ();
if (-f $CONFIG_FILE) {
    %conf = Config::General->new( $CONFIG_FILE )->getall();
}

# Now that we've dropped privileges, create the logger. If we do it in reverse
# order, the daemon won't be able to write to the logger.
my $logger;
if ( not $LOGGER_CONF or ! -f $LOGGER_CONF ) {
    use Log::Log4perl qw(:easy);

    my $output_level = $INFO;
    if ( $DEBUGFLAG ) {
        $output_level = $DEBUG;
    }

    my %logger_opts = (
        level  => $output_level,
        layout => '%d (%P) %p> %F{1}:%L %M - %m%n',
    );

    Log::Log4perl->easy_init( \%logger_opts );
    $logger = get_logger( "perfSONAR_PS" );
}
else {
    use Log::Log4perl qw(get_logger :levels);

    my $output_level = $INFO;
    if ( $DEBUGFLAG ) {
        $output_level = $DEBUG;
    }

    Log::Log4perl->init( $LOGGER_CONF );
    $logger = get_logger( "perfSONAR_PS" );
    $logger->level( $output_level ) if $output_level;
}

my @services = (
    get_service_object("mysql"),
    get_service_object("httpd"),
    get_service_object("cassandra"),
    get_service_object("owamp"),
    get_service_object("bwctl"),
    get_service_object("npad"),
    get_service_object("ndt"),
    get_service_object("regular_testing"),
    get_service_object("ls_registration_daemon"),
    get_service_object("ls_cache_daemon"),
    get_service_object("config_daemon"),
);

# do a 'restart' pass if the "--regular-restart" flag was specified
if ($REGULAR_RESTART) {
    foreach my $service ( @services ) {
        my ($status, $res);

        if ($service->disabled) {
            $logger->debug("Skipping ".$service->name);
            next;
        }

        unless ($service->needs_regular_restart) {
            $logger->debug("Skipping ".$service->name.". doesn't need regular restarts");
            next;
        }

        $logger->info("Regular restart for ".$service->name.".");

        # try and kill any remnants the service and restart
        ($status) = $service->kill();

        # Pause some to make sure it's really dead.
        sleep(5);

        $status = $service->start();
    }
}

# do a single pass to see if the services are up, and try to start them. Report any that are down.
foreach my $service ( @services ) {
    my ($status, $res);

    if ($service->disabled) {
        $logger->debug("Skipping ".$service->name);
        next;
    }

    if ($service->check_running) {
        $logger->debug($service->name." is up");
        next;
    }

    $logger->debug("Service ".$service->name." is down.");

    my $report = "Service ".$service->name." is down.";

    # now we need to try and kill any remnants the service and restart
    $service->kill;

    # Pause some to make sure it's really dead.
    sleep(5);

    $status = $service->start;
}

# do a single pass of all the services that are up, and send "OK" messages for all the ones that are running.
foreach my $service ( @services ) {
    my ($status, $res);

    if ($service->check_running) {
        $logger->debug($service->name." is up");
    }
}
