#!/usr/bin/perl

=pod

=head1 NAME speak / say

Simply speaks the passed in message, clipboard or file (invoked as speak or say)

=head1 VERSION

=over

=item Author

Andrew DeFaria <Andrew@DeFaria.com>

=item Created:

Wed 24 Feb 2021 12:01:12 PM PST

=back

=head1 SYNOPSIS

 Usage: speak | say [-usa|ge] [-h|elp] [-v|erbose] [-de|bug]
              [-c|lipboard] [-f|ile <filename>] [-p|ersona <name>]
              [-a|pp <name>] [-l|astmsg | -r|epeatmsg]
              [-o|utput <filename>] ["message"]

 Where:
   -usa|ge:                 Print this usage
   -h|elp:                  Detailed help
   -c|lipboard:             Speak the contents of the clipboard
   -f|ile <filename>:       Speak the contents of <filename>
   -p|ersona <name>:        Use a specific persona voice
   -a|pp <name>:            Specify application name to tag in the log
   -l|astmsg | -repeatmsg:  Repeat the last spoken message from the log
   -o|utput <file>:         Save output speech to specified audio file
   "message":               Speak the message

=head1 DESCRIPTION

This script speaks the contents of the passed in message, clipboard or file.
Can be called as either 'speak' or 'say'.

=cut

use strict;
use warnings;
use feature 'signatures';
no warnings 'experimental::signatures';

use Getopt::Long;
use Pod::Usage;
use FindBin;
use lib "$FindBin::Bin/../lib";

use Speak qw(speak last_message);
use Clipboard;

sub error ($msg, $exit_code = 1) {
    print STDERR "ERROR: $msg\n";
    exit $exit_code;
}

my $verbose = 0;
my $debug   = 0;

my %opts = (
  usage => sub {pod2usage},
  help  => sub {pod2usage (-verbose => 2)},
  ## no critic (Variables::RequireLocalizedPunctuationVars)
  verbose => sub {$verbose = 1; $ENV{VERBOSE} = 1},
  debug   => sub {$debug   = 1; $ENV{DEBUG}   = 1},
);

## Main
GetOptions (
  \%opts,
  'usage',
  'help',
  'verbose',
  'debug',
  'clipboard',
  'file=s',
  'persona=s',
  'output=s',
  'app=s',
  'lastmsg|repeatmsg|repeat',
) || pod2usage;

my $msg = join ' ', @ARGV;

if ($opts{lastmsg}) {
  if ($opts{clipboard} || $opts{file} || $msg) {
    error 'Cannot specify -lastmsg/-repeatmsg with other message sources', 1;
  }
  my ($last, $tag) = last_message ();
  error 'No previous spoken message found in log', 1 unless defined $last;
  $msg = $last;
} elsif ($opts{clipboard}) {
  if ($opts{file}) {
    error 'Cannot specify both -clipboard and -file', 1;
  } elsif ($msg) {
    error 'Cannot specify both -clipboard and <message>', 1;
  } else {
    $msg = eval {
      open my $olderr, '>&', \*STDERR;
      open STDERR, '>', '/dev/null';
      my $res = Clipboard->paste;
      open STDERR, '>&', $olderr;
      $res;
    };
    if (!defined $msg || $msg eq '') {
      error 'Clipboard is empty or inaccessible', 1;
    }
  }    # if
} elsif ($opts{file}) {
  if ($msg) {
    error 'Cannot specify both -file and <message>', 1;
  } else {
    open my $file, '<', $opts{file}
      or error "Unable to open $opts{file} - $!", 1;

    $msg = do {local $/; <$file>};

    close $file;
  }    # if
}    # if

speak ($msg, undef, undef, $opts{persona}, $opts{output}, $opts{app});
