#!/usr/bin/perl

################################################################
#
# MythTv <-> nvram script
#
# (C) 2009 Adrian Ulrich
#
#

use strict;
use LWP::Simple;
use XML::Simple;
use Data::Dumper;
use Date::Parse;
use Sys::Load qw(uptime);

use constant MIN_DELTA => 60*15;
use constant FFILE      => '/tmp/force-shutdown';
use constant IRFILE     => '/tmp/irw';

die "Run me as root\n" if $< != 0;

# Read commandline args
my $FORCED      = ( $ARGV[0] eq '--force' ? 1 : 0 );
my $NVONLY      = ( $ARGV[0] eq '--nvram' ? 1 : 0 );


my $NOW         = int(time());                               # Current unixtime
my $UPTIME      = int(uptime());                             # System uptime
my $REMOTE      = 0;                                         # Remote in use?

if( (-s IRFILE) && ((-M "/tmp/irw")*86400) < 60*60*3 ) {     # Set remote to IN_USE if used within 3 hours
	$REMOTE = 1;
}

my $xml_ref     = XMLin( get("http://localhost:6544/xml") ); # Raw XML reference
my $schedref    = $xml_ref->{Scheduled}->{Program};          # Reference to jobschedule
my $encref      = $xml_ref->{Encoders}->{Encoder};
my $jobref      = $xml_ref->{JobQueue};
my $DOES_RECORD = 0;                                         # True if we are recording (or watching TV)
my $DOES_JOBS   = 0;                                         # True if there are queued jobs
my $NEXT_REC    = 0;                                         # Timestamp of next recording

# Set encoder state
if(exists($encref->{state})) { $DOES_RECORD = $encref->{state};                      }
else                         { map( $DOES_RECORD+= $_->{state}, values( %$encref ) ) }

# Guess next record time
foreach my $xref (@$schedref) {
	my $tstamp = str2time($xref->{Recording}->{recStartTs});
	if($tstamp >= $NOW && (!$NEXT_REC or $NEXT_REC > $tstamp)) {
		$NEXT_REC = $tstamp;
	}
}

if($jobref->{count}) {
	# Struct has some jobs..
	$jobref->{Job} = { depp => $jobref->{Job} } if $jobref->{count} == 1; # XXXX!!
	foreach my $jref (values(%{$jobref->{Job}})) {
		$DOES_JOBS++ if $jref->{status} < 0x0100;
	}
}


printf("Currenty recording : %s\n", $DOES_RECORD ? 'yes' : 'no'                           );
printf("Jobs scheduled     : %s\n", $DOES_JOBS   ? "yes ($DOES_JOBS)" : 'no'              );
printf("Next recording     : %s\n", $NEXT_REC    ? "at ".localtime($NEXT_REC) : '-never-' );
printf("Remote in use      : %s\n", $REMOTE      ? 'yes' : 'no'                           );


if($NEXT_REC) {
	if(markNext($NEXT_REC)) {
		print "Must update nvram...\n";
		system(" /usr/local/bin/nvram-wakeup -C /etc/nvram-wakeup.conf --directisa -n -s $NEXT_REC");
	}
}
else {
	print "No new recordings.\n";
	if(markNext(0)) {
		print "Disabling autostart via nvram...\n";
		system("/usr/local/bin/nvram-wakeup -C /etc/nvram-wakeup.conf --directisa -d");
	}
}


exit 0 if $NVONLY; # Only update nvram





if($DOES_JOBS == 0 && $DOES_RECORD == 0 && $UPTIME >= MIN_DELTA && ( $NEXT_REC < $NOW or ( $NEXT_REC-$NOW >= MIN_DELTA ) ) ) {
	print "Considering shutdown\n";
	if(!$REMOTE or $FORCED) {
		shutdownSystem();
	}
}
elsif($FORCED) {
	my $fage = getFage();
	print "ForceFile is $fage seconds old\n";
	if($fage && $fage < 20 ) {
		print "Shutting down\n";
		shutdownSystem();
	}
	else {
		print "Warning user\n";
		system("touch ".FFILE);
		system("/opt/myth/bin/mythtvosd --template=alert --alert_text='$DOES_JOBS jobs and $DOES_RECORD recordings running. Hit POWER within 20 seconds to force shutdown.'");
	}
}




##########################################################
# Remember last nvram date
sub markNext {
	my($when) = @_;
	my $last = `cat /var/tmp/.nvtime 2>/dev/null`;
	chomp $last;
	if($last != $when) {
		`echo $when > /var/tmp/.nvtime`;
		return 1;
	}
	return 0;
}

##########################################################
# Get FileAge
sub getFage {
	return ( (-M FFILE)*86400 );
}

##########################################################
# Force halt
sub shutdownSystem {
	print ">> SYSTEM IS GOING DOWN! <<\n";
	system("/sbin/halt");
}


