#!/usr/bin/perl

print scalar localtime, "\n";

my @sessions;
open INP, "loginctl --no-legend --no-pager --all --full list-sessions |" or die "Run list-sessions: $!\n";
while (<INP>)
    {
    chomp;
    s/^\s*//;
    my ( $session, $uid, $user, $seat ) = split / +/;
    push @sessions, { Session=>$session, Uid=>$uid, User=>$user, Seat=>$seat };
    }
close INP or die "Close list-sessions: $!\n";

$OK_sleep = 1;

printf <<EOT;
Session Seat     User     Service           State    IdleHint
        Display  Uid      Type              Active   SleepOK
==============================================================
EOT

for my $s ( @sessions )
    {
    open INP, "loginctl --no-legend --no-pager --all --full -p Display -p Active -p State -p Type -p Service -p IdleHint show-session $s->{Session}|"
	or die "Run show-session: $!\n";
    while (<INP>)
	{
	chomp;
	my ( $prop, $val ) = split /=/, $_, 2;
	$s->{$prop} = $val;
	}
    close INP or die "Close show-session: $!\n";

    $s->{CanSleep} =
	(
	    (
	    $s->{IdleHint} eq 'yes' && $s->{Service} ne 'sshd' ||
	    $s->{Service} eq 'lightdm-greeter' ||
	    $s->{Service} =~ '^lightdm' && $s->{State} eq 'closing' ||
	    $s->{Service} eq 'sshd' && $s->{State} eq 'closing'
	    )
#	&& $s->{Type} ne 'tty'
	) || 0; # Prefer 0 as false value over empty string.

    printf "%-7s %-8s %-8s %-17s %-8s %-8s\n", map $s->{$_}, qw( Session Seat User Service State IdleHint );
    printf "%-7s %-8s %-8s %-17s %-8s %-8s\n", '', map $s->{$_}, qw( Display Uid Type Active CanSleep );

    $OK_sleep &&= $s->{CanSleep}
    }

print "\nOK_sleep: $OK_sleep\n";

if ( $OK_sleep )
    {
    use Glib;
    local undef $/;
    open INP, "gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.ListInhibitors |" or die "Run list-inhibitors: $!\n";
    $v = Glib::Variant::parse (undef, <INP> );
    for ( @{$v->get($v->get_type_string)->[0]} )
	{
	( $what, $who, $why, $mode ) = @$_;
	if ( $what =~ /sleep/ && $mode =~ /block/ )
	    {
	    printf "What:%s\n Who:%s\n Why:%s\nMode:%s\n", $what, $who, $why, $mode;
	    $OK_sleep = 0;
	    # last; # commented out to get all inhibitors in output
	    }
	}
    close INP;
    print "\nOK_sleep: $OK_sleep\n" unless $OK_sleep;
    }

if ( $OK_sleep )
    {
    open INP, "su -c 'vboxmanage list runningvms' user2 |" or die "Run vboxmanage: $!\n";
    while (<INP>)
	{
	( $name ) = /^"(.*)"/;
	if ( $name eq 'Win10' )
	    {
	    print "! $_";
	    $OK_sleep = 0;
	    }
	else
	    {
	    print ". $_";
	    }
	}
    close INP;
    print "\nOK_sleep: $OK_sleep\n" unless $OK_sleep;
    }

if ( $OK_sleep )
    {
    print "\nOK_sleep: $OK_sleep\n Suspending\n";
    system "systemctl suspend"
    }
