#!/usr/bin/env perl

use strict;
use warnings;
use lib 'lib';
use utf8;

use Getopt::Long;
use Subtitle::SSA;

sub usage {
  my ($msg) = @_;
  print $msg, "\n" if $msg;
  print <<USAGE;
Usage: ssa-retime <mode> [<options>] -i <file> [ -o <file>]

Modes are:
  * framerate       Retime whole file from one fps to another.
  * points          Retime file specifying point(s) & time shift for it.
  * shift           Shift whole file or it's part for given time.

Common options:
  -h                This help.
  -i <file>         Input file. (mandatory).
  -o <file>         Output file. Default: write to stdout.
  -v                Be verbose.

Specific options for 'shift' mode:
  -S <string>       Retime only events with specified style.
                    This option may be given more than once.
  -s <time>         Start time of period, that will be changed.
                    Default: first event.
  -e <time>         End time of period, that will be changed.
                    Default: the latest time found in file.
  -l <time>         Duration of period above. This option require '-s'
                    You may select either '-o' or '-e' at the same time.
  -t <time>         Change time for this value.

Specific options for 'framerate' mode:
  -f <float>        Source framerate. Default: 25.0 fps.
  -F <float>        Target framerate.

Specific options for 'points' mode:
  -p <time>/<time>  Point of fixup & time shift in it. Option can be
                    specified more than once. (see man for details)
                    Both args must be in form of [-][[h:]m:]s[.ms].
USAGE
  exit 1;
}

########### init ###################
$| = 1;

my $mode = shift @ARGV;

my @points;
my %opts = ( loglevel => 0, inrate => 25.0 );
#GetOptions("qvhi:o:S:f:F:p:t:s:e:l:", \%opts)
GetOptions(
  'h|help'        => \&usage,
  'v|verbose+'    => \$opts{loglevel},
  'i|infile=s'    => \$opts{infile},
  'o|outfile=s'   => \$opts{outfile},

  'S|style=s'     => \$opts{style},
  's|shiftstart=s'=> \$opts{shiftstart},
  'e|shiftend=s'  => \$opts{shiftend},
  'l|shiftlen=f'  => \$opts{shiftlen},

  't|shifttime=f' => \$opts{shifttime},

  'f|inrate=f'    => \$opts{inrate},
  'F|outrate=f'   => \$opts{outrate},

  'p|point'       => \@points,
);

($opts{infile} and -f $opts{infile})
  or usage("Input file not exists");

if ($mode eq 'framerate') {
  $opts{outrate}
    or usage("You should set at least '-F' option in this mode");
  ($opts{inrate} != 0.0 and $opts{outrate} != 0.0)
    or usage("Framerate can't be zero");
} elsif ($mode eq 'shift') {
  $opts{shifttime}
    or usage("You should set '-t' option in this mode");
  (not $opts{shiftstart} or $opts{shiftstart} > 0.0)
    or usage("Shift start must be positive time");
  (not $opts{shiftend}   or $opts{shiftend} > 0.0)
    or usage("Shift end must be positive time");
  (not $opts{shiftlen}   or $opts{shiftlen} > 0.0)
    or usage("Shift length must be positive time");
} elsif ($mode eq 'points') {
  scalar(@points)
    or usage("You should specify at least one shift point");
  foreach my $point (@points) {
    ...
  }
} else {
  usage("Incorrect mode: $mode (see help below)");
}

my $ssa = Subtitle::SSA->new(debug => !!$opts{loglevel});
if ($ssa->from_file($opts{infile}) < 0) {
  warn "Can't parse input file: $opts{infile}\n";
  exit 1;
}

if ($mode eq 'framerate') {
  my $mod = $opts{inrate} / $opts{outrate};
  foreach my $event (@{ $ssa->{events} }) {
    $event->{start} *= $mod;
    $event->{end}   *= $mod;
  }
} elsif ($mode eq 'shift') {
  my $style = $opts{style};
  my $start = $opts{shiftstart} // 0.0;
  my $end   = $opts{shiftend} // (($opts{shiftlen}) ? $start + $opts{shiftend} : undef);
  my $mod   = $opts{shifttime};
  foreach my $event (@{ $ssa->{events} }) {
    next if ($style and $event->{style} ne $style);
    next if ($start and $event->{start} < $start);
    next if ($end   and $event->{end}   > $end);
    $event->{start} += $mod;
    $event->{end}   += $mod;
  }
} elsif ($mode eq 'points') {
  ...;
}

exit 0;