#!/usr/bin/perl
#
# Notes:
#   1. runs from root
#   2. deactivates Display Server

use strict;
use LWP::UserAgent;
use HTTP::Request::Common;
use JSON;
use Data::Dumper;
use Getopt::Long qw(:config no_ignore_case bundling);

# CONS -------------------------------------------------------------------------
my $DS_VAR=$ENV{DS_VAR} || '/var/ds';
my $DS_CONF="$DS_VAR/conf/ds.conf";
my $WALL_CONF="$DS_VAR/conf/wall.conf";
my $ACTIVATE_LOGS="$DS_VAR/log/activate";
my $LOG="$ACTIVATE_LOGS/deactivate.log";

# VARS -------------------------------------------------------------------------
my $DryRun;
my %DSCfg;
my $AvatarID;
my $Endpoint;
my $DSID;
my $WallID;

# PROC -------------------------------------------------------------------------

#-------------------------------------------------------------------------------
sub Log { # print message to log
#-------------------------------------------------------------------------------
    my $msg=shift;
    open  LOG, ">>$LOG";
    print LOG scalar localtime().'| '.$msg;
    close LOG;
}

#-------------------------------------------------------------------------------
sub prlog { # print message to screen and place in a log
#-------------------------------------------------------------------------------
    my $msg=shift;
    $msg = "[dry-run] $msg" if $DryRun;
    print $msg;
    Log $msg;
}

#-------------------------------------------------------------------------------
sub Errlog { # print error to the log and screen then die
#-------------------------------------------------------------------------------
    Log "\nERROR: @_\n";
    die "\nERROR: @_\n";
}

sub read_conf {
    my $file = shift;
    open FH, $file or return undef;
    my %conf = map {/^(\w+)=(.*)$/} grep {/^\w+=/} <FH>;
    close FH;
    return \%conf;
}

sub vmx2_api {
    my ($http_method, $api, $data) = @_;

    my $url = "https://$Endpoint/api/vmx2/$api";
    my $req = HTTP::Request->new($http_method, $url);
    $req->header('Content-Type' => 'application/json');
    $req->header('X-avatarid', $AvatarID);
    $req->content(encode_json($data));
    my $lwp = LWP::UserAgent->new(requests_redirectable => ['GET', 'HEAD', 'POST', 'PUT']);
    if ($DryRun) {
        prlog "vMX2 API Request: $http_method $url. Data:\n".Dumper($data);
        return 1;
    }
    my $resp = $lwp->request($req);
    if (!$resp->is_success) {
        my $msg = "Error performing vMX2 API request (HTTP error): ".$resp->code." ".$resp->message;
        my $json = eval { decode_json $resp->content };
        $msg .= "\n".$json->{error} if not $@ and $json and $json->{error};
        prlog "$msg\n";
        return 0;
    }
    my $json = decode_json($resp->content);
    if ($json->{error}) {
        prlog "Error performing vMX2 API request (App error): ".$resp->content."\n";
        return 0;
    }
    return 1;
}


sub stop_ds {
    prlog "Stopping DS service\n";
    system("systemctl stop ds") if not $DryRun;
}

sub unregister_ds {
    prlog "Unregistering DS objects from JetStream\n";
    my $request = {};
    $request->{wall_id} = { id => { uuid => $WallID } } if $WallID;
    my $result = vmx2_api(
        'DELETE', "ds/$DSID", $request
    );
    if (not $result) {
        prlog "Cannot remove corresponding video wall configurations from JetStream\n";
    } else {
        prlog "Display Server unregistered successfully\n";
    }
}

sub deactivate {
    GetOptions(
        'dry-run'  => \$DryRun
    ) or die "Invalid options\n";

    stop_ds();

    if (-f $DS_CONF) {
        my $cfg = read_conf $DS_CONF;
        Errlog("Cannot open $DS_CONF: $!") if not $cfg;
        %DSCfg = %$cfg;

        $DSID     = $DSCfg{OBJID};
        $Endpoint = $DSCfg{ENDPOINT};
        $AvatarID = $DSCfg{AVATARID};

        if (-f $WALL_CONF) {
            $cfg = read_conf $WALL_CONF;
            prlog "ERROR: Unable to read wall.conf: $!\n" if not $cfg;
            $WallID = $cfg->{OBJID} if $cfg;
        }

        unregister_ds();
    }
}


# MAIN =========================================================================

deactivate();

END {
    prlog "Removing DS_VAR\n";
    system("rm -rf $DS_VAR") if not $DryRun;
    prlog "Done\n";
}
