#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;

# CONS
my $DS_BIN = "/opt/ds/bin";
my $CMD = "/var/vnlk/ds/cmd";
my $SLEEP = 3;
my $ACTIVATE_TIMEOUT = 300;
my $DEACTIVATE_TIMEOUT = 300;
my $SYSTEMCTL_TIMEOUT = 120;

# VAR
my $last_check = 0;
my $has_cmd = 0;

# SIG
$SIG{INT} = $SIG{TERM} = sub { 
    log_warn("Got signal. Shutting down.");
    exit;
};

# SUB
sub _log {
    my ($level, $msg) = @_;
    chomp $msg;
    warn scalar(localtime())." | $level | $msg\n";
}

sub log_info { _log 'info', shift }
sub log_warn { _log 'warn', shift }
sub log_error { _log 'error', shift }

sub timeout_cmd {
    my ($cmd, $timeout) = @_;
    my $out;

    eval {
        $SIG{ALRM} = sub { die "ALARM" };
        alarm $timeout;
        $out = `sudo $cmd 2>&1`;
    };
    alarm 0;
    if ($@ and $@=~/ALARM/) {
        log_error("Command '$cmd' was interrupted: timeout exceeded");
    } else {
        if ($? != 0) {
            log_error("Command '$cmd' finished with errors");
        } else {
            log_info("Command '$cmd' finished successfully");
        }
    }
    log_info("Command '$cmd' output: \n$out");
}

sub ds_start {
    timeout_cmd "systemctl enable ds", $SYSTEMCTL_TIMEOUT;
    timeout_cmd "systemctl start ds", $SYSTEMCTL_TIMEOUT;
}

sub ds_stop {
    timeout_cmd "systemctl disable ds", $SYSTEMCTL_TIMEOUT;
    timeout_cmd "systemctl stop ds", $SYSTEMCTL_TIMEOUT;
}

sub ds_activate {
    timeout_cmd "$DS_BIN/activate -a", $ACTIVATE_TIMEOUT;
}

sub ds_deactivate {
    timeout_cmd "$DS_BIN/deactivate", $DEACTIVATE_TIMEOUT;
}

sub check_cmd {
    return if not -f $CMD;
    if (not open FH, $CMD) {
        log_error("Cannot open $CMD: $!");
        unlink $CMD;
        return;
    }
    my $cmd = <FH>;
    chomp $cmd;
    close FH;
    unlink $CMD or log_warn("Cannot delete $CMD: $!");
    if ($cmd !~ /^(start|stop|activate|deactivate)$/) {
        log_warn("Bad command: $cmd");
        return;
    }
    log_info("Executing command: $cmd");
    for ($cmd) {
        /^start$/      and do { ds_start; last };
        /^stop$/       and do { ds_stop; last };
        /^activate$/   and do { ds_activate; last };
        /^deactivate$/ and do { ds_deactivate; last };
    }
}


sub main {
    log_info("Avatar display server controller");

    while (1) {

        check_cmd;

        sleep $SLEEP;
    }
}

main;
