#!perl

# Author: Skye Shaw (skye.shaw@gmail.com)
# Source: https://github.com/sshaw/Time-Timecode
# Copyright: Copyright (c) 2009-2016 Skye Shaw. All rights reserved.
# License: This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
# Description: Timecode conversion program. A front end for the Time::Timecode module.

use strict;
use warnings;

use Getopt::Long;
use Time::Timecode;

Getopt::Long::Configure('bundling');

my $VERSION = '0.01';

my ($convert, $format, $input, $output, $quiet);

my $ok = GetOptions('c|convert:s' => \&convert_options,
		    'f|format:s' => \$format,
		    'h|help' => sub { help(); exit },
		    'i|input:s' => \&input_options,
		    #'o|output:s' => \$output,
		    'q|quiet' => \$quiet,
		    'v|version' => \&version);

usage() unless $ok;

if (@ARGV) {
  my $tc = parse_timecode(shift, $input);
  exit 1 unless $tc;

  print convert_timecode($tc), "\n";
}
else {

  my @conversions;
  while (<>) {
    next unless /\w/;
    chomp;

    my $tc = parse_timecode($_, $input);
    next unless $tc;

    push @conversions, [$tc->to_string, convert_timecode($tc)]
  }

  output_timecode(@$_) for @conversions;
}

sub output_timecode {
  # TODO: output formats
  print "$_[0] $_[1]\n";
}

sub parse_timecode {
  my $value = shift;
  my $options = shift || {};
  my $tc = eval { Time::Timecode->new($value, $options) };

  die $@ if $@ && !$quiet;

  return $tc;
}

sub input_options {
  $input = parse_timecode_options(@_);
}

sub convert_options {
  $convert = parse_timecode_options(@_);
}

sub convert_timecode {
  my $tc = shift;
  $tc = $tc->convert($convert->{fps}, $convert) if $convert;
  return $tc->to_string($format);
}

sub parse_timecode_options {
  my $value = pop;
  my $options = {};

  if ($value =~ /^(\d+(?:.\d+)?)(N?D)?$/i) {
    $options->{fps} = $1;
    $options->{dropframe} = defined $2 && lc $2 eq 'd' ? 1 : 0;
  }
  else {
    map {
      my ($k, $v) = split /=/;
      $options->{$k} = $v;
    } split /,/, $value
  }

  return $options;
}

sub help {
  print STDERR "usage: timecode [-h] [-c spec] [-f format] [-i spec] [timecode]\n";
  print STDERR<<HELP;
    -h --help		   option help
    -c --convert spec      convert timecode according to `spec'
 			   `spec' can be a number of FPS proceeded by an optional `N' or `ND' or, a comma
		 	   separated list of key=value. key can be fps, dropframe, delimiter, frame_delimiter
    -f --format  format    output timecode according to `format' e.g., '%H:%M:%S at %r FPS'.
			   %H=hours, %M=mins, %S=secs, %f=frames, %i=total frames, %r=frame rate, %s=frames in secs
    -i --input   spec      process incoming timecodes according to `spec'; see -c for more info
    -q --quiet             ignore invalid timecodes
    -v --version           print version information

If no timecode is given timecodes will be read from stdin.
For more info and examples visit: https://github.com/sshaw/Time-Timecode
HELP
}

sub usage {
  help();
  exit 1;
}

sub version {
  print "timecode v$VERSION (Time::Timecode v$Time::Timecode::VERSION)\n";
  exit;
}
