#!/usr/bin/perl

use strict;
use lib qw(lib);
use Event;
use Getopt::Long;
use Video::TranscodeRC;

my $USAGE = <<__EOU;

Usage: transcode-rc [-b batch-file] [-v verbosity] -i movie-file

Options:
    -i|--movie-file     Name of the movie file to process (mandatory)
    -b|--batch-file     Name of a batch file (see below)
    -v|--verbose        Verbosity: 0=quiet, 1=brief, 2=full
                
Description:
    This program uses Video::TranscodeRC to remote control
    transcode processing the given movie-file. It's intended
    for testing purposes, but Video::TranscodeRC can be used
    for real applications.
    
    Everything you type into stdin will be passed as-is
    to transcode's remote control socket. Depending on the
    verbosity level, everything received from transcode's
    stdout and the socket is printed to your console.

Batch processing;
    You can drive batch files with transcode-rc. These are simple
    text files with one command per line. Empty lines and those
    starting with a # sign are ignored.
    
    The following commands are recognized:
    
    sleep n             Sleep n seconds (n may be fractional)
    exit                Exit transcode-rc

    Everything else is passed through as-is to transcode and
    such is expected to be a valid transcode socket command.

__EOU

my $batch_commands_sent = 0;

main: {
    my $movie_file;
    my $batch_file;
    my $verbose;

    my $ok = GetOptions (
        "movie-file|i=s" => \$movie_file,
        "batch-file|b=s" => \$batch_file,
        "verbose|v=i"    => \$verbose,
    );
    
    if ( !$ok or !$movie_file ) {
        print $USAGE;
        exit 1;
    }
    
    my ($w, @failed, @ok);
    my $rc = Video::TranscodeRC->new (
        command     => "transcode -i $movie_file",
        close_cb => sub {
            my ($what) = @_;
            $verbose && print "CLOSED: $what\n";
            $w->broadcast;
        },
        socket_data_cb => sub {
            my ($data) = @_;
            $data =~ s/\s+$//;
            $verbose > 1  && print "SOCK: $data\n";
        },
        tc_data_cb => sub {
            my ($data) = @_;
            $data =~ s/\s+$//;
            $data =~ s/^/TC: /mg;
            $verbose > 1 && print $data,"\n";
        },
        ok_cb => sub {
            my ($line) = @_;
            $verbose && print "OK: $line\n";
            push @ok, $line;
        },
        failed_cb => sub {
            my ($line) = @_;
            $verbose && print "FAILED: $line\n";
            push @failed, $line;
        },
    );
    $rc->start;
    
    batch($rc, $batch_file, $verbose) if $batch_file;
    
    my $watcher = AnyEvent->io (
        fh      => \*STDIN,
        poll    => "r",
        cb      => sub { control($rc) },
    );
    
    $w = AnyEvent->condvar;
    $w->wait;
    
    #-- TranscodeRC itself sends a "pause" command
    ++$batch_commands_sent;

    my $ok = @failed == 0;
    $ok = 0 if $ok && $batch_file && $batch_commands_sent != @ok;

    if ( $verbose ) {
        if ( @ok ) {
            print "\nSuccessfully executed commands:\n";
            print "    ",join("\n    ",@ok),"\n";
        }
        if ( @failed ) {
            print "\nFailed commands:\n";
            print "    ",join("\n    ",@failed),"\n";
        }
    }
    
    $verbose && print "\n";

    exit !$ok;
}

sub control {
    my ($rc) = @_;
    
    my $buffer;
    if ( ! sysread(STDIN, $buffer, 4096) ) {
        $rc->stop;
        return;
    }

    my @lines = split(/\n/, $buffer);
    foreach my $line ( @lines ) {
        $rc->send($line);
    }

    1;
}

sub batch {
    my ($rc, $file, $verbose) = @_;
    
    open (my $fh, $file) or die "can't read $file";
    next_batch_command($rc, $fh, $verbose);

    1;    
}

sub next_batch_command {
    my ($rc, $fh, $verbose) = @_;
    
    if ( eof($fh) ) {
        close $fh;
        return;
    }
    
    while ( <$fh> ) {
        my $command = $_;
        chomp $command;
        next if $command =~ /^\s*#/ || $command !~ /\S/;

        $verbose && print "BATCH: $command\n";

        if ( $command =~ /^sleep\s+([\d.]+)/ ) {
            my $w;
            $w = AnyEvent->timer (
                after => $1,
                cb    => sub {
                    $w = undef;
                    next_batch_command($rc, $fh, $verbose);
                },
            );
            return;
        }
        elsif ( $command =~ /^exit/ ) {
            $rc->stop;
            return;
        }
        else {
            ++$batch_commands_sent;
            $rc->send($command);
        }
    }

    $verbose && print "BATCH: eof\n";

    close $fh;
    
    1;
}
