#! /usr/bin/perl -w
## $Id: kodi-progress,v 1.2 2020/03/30 03:00:11 homer Exp $

use strict;
use Getopt::Long;
use Pod::Usage;
use JSON;
use LWP::UserAgent ();
use IO::Socket::INET;

my ($help, $do_echo, $do_udp_send) = (0, 0, 0);
my ($dhost, $dport) = qw(esp1 4444);
GetOptions (
    'echo' => \$do_echo,
    'host=s' => \$dhost,
    'h|help' => \$help,
    'port=i' => \$dport,
    'udp!' => \$do_udp_send,
    ) or pod2usage(2);
pod2usage(1) if $help;
$do_echo = 1 if !$do_udp_send;

=head1 NAME

kodi-progress

=head1 SYNOPSIS

kodi-progress [options]

 Options:

   --echo               Print progress to terminal in addition to network
   --host=HOST          Override default target hostname
   --port=PORT          Override default target port
   --no-udp             Disable sending progress via network
                        (implies --echo)
   -h, --help           Print this help message

=head1 DESCRIPTION

B<kodi-progress> reads player progress information and forwards it to
a esp8266-max7219-relay display.

=cut

my $ua = LWP::UserAgent->new(timeout => 5);
$ua->credentials('<hostname>:<port>', 'XBMC', '<username>', '<password>');
my $url = 'http://<hostname>/jsonrpc';

sub call($$$) {
    my ($ua, $url, $call) = @_;
    $call->{jsonrpc} = '2.0';
    $call->{id} = 'foo';

    return $ua->post($url,
                     'Content-Type' => 'application/json',
                     Content => to_json $call);
}

sub player_status_call($) {
    my $player_id = shift;
    return {
        method => 'Player.GetProperties',
        params => {
          playerid => $player_id,
          properties => [qw(time totaltime percentage)],
        },
    };
}

my $sock = IO::Socket::INET->new(PeerAddr => $dhost,
                                 PeerPort => $dport,
                                 Proto => 'udp');

sub is_error($) {
    my $response = shift;
    return 1 if $response->is_error;
    my $decoded = from_json $response->decoded_content;

    return defined $decoded->{error};
}

while (1) {
    my $response = call($ua, $url, player_status_call(1));
    $response = call($ua, $url, player_status_call(0)) if is_error($response);

    my $msg = '        ';
    if (is_error($response)) {
        ;
    } else {
        my $response_object = from_json $response->decoded_content;
        my $r = $response_object->{result};

        my $time = $r->{time};
        my $len  = $r->{totaltime};

        my $time_s =
            $time->{hours} * 3600 + $time->{minutes} * 60 + $time->{seconds};
        my $len_s =
            $len->{hours} * 3600 + $len->{minutes} * 60 + $len->{seconds};

        if ($len_s > 0) {
            my $remaining_s = $len_s - $time_s;
            my $h = int($remaining_s / 3600);
            my $m = int($remaining_s / 60) % 60;
            my $s = $remaining_s % 60;

            if ($h > 0) {
                $msg = sprintf '%d:%02d:%02d', $h, $m, $s;
                $msg = '-' . $msg if $h < 10;
            } else {
                $msg = sprintf '-%d:%02d', $m, $s;
                $msg = sprintf '%8.8s', $msg;
            }
        }
    }

    printf STDERR "\r%s", $msg if $do_echo;

    my $cmd = pack 'C', 0x80;
    $sock->send($cmd . $msg) if $do_udp_send;
    sleep 0.45;
}
