#!/usr/bin/env perl

use strict;
use warnings;

use lib "lib";
use Time::TAI::Simple;

my %OPT  = ();
my @URLS = ();
foreach my $arg ( @ARGV ) {
    if    ($arg =~ /^\--+(.+?)\=(.*)/) { $OPT{$1} = $2; }
    elsif ($arg =~ /^\--+(.+)/       ) { $OPT{$1} = -1; }
    elsif ($arg =~ /^\-(.+)/         ) {
        my $args = $1;
        foreach my $c (split(//,$args)) { $OPT{$c} = -1; }
    } else {
        push(@URLS, $arg);
    }
}

exit(usage()) if ($OPT{h} || $OPT{help} || $OPT{'?'});

my %opt_h = (
    download_leapseconds => 1,
    do_not_load_leapseconds => 1,
    base_time => 0  # don't bother calculating base_time; we're not using it.
);

for my $param (keys %OPT) {
    my $opt_key = join('_', split(/\-/, $param));
    $opt_h{$opt_key} = $OPT{$param};
}
$opt_h{leapseconds_pathname} = $OPT{'pathname'} if (defined($OPT{'pathname'}));
$opt_h{download_urls} = \@URLS if (scalar(@URLS) > 0);

my $tai_or = Time::TAI::Simple->new(%opt_h);

if (!defined($tai_or->{dl_fr})) {
    print STDERR "download failed\n" unless ($OPT{q} || $OPT{quiet});
    exit(1);
}

print "$tai_or->{dl_fr}\n" if     ($OPT{'show-url'});
print "$tai_or->{dl_to}\n" unless ($OPT{'q'} || $OPT{'quiet'});
exit(0);

sub usage {
    print join("\n", (
        "Usage: $0 [options]",
        "Options are:",
        "    --add-agent=<string>",
        "           Add the specified User-Agent string to the internal list",
        "    --add-agent=\"<string>|<string>|...\"",
        "           Add the specified User-Agent strings to the internal list",
        "    --agent=<string>",
        "           Use the specified User-Agent string",
        "    --churn-agent",
        "           On failure, pick a random User-Agent string for next try",
        "           (Most useful when --retry=N is set to N > 1)",
        "           (Does not work with --force-edge)",
        "    --debug",
        "           Show annoying descriptions of what it is doing (ignores -q)",
        "    --force-edge",
        "           Always use the first User-Agent string in the list",
        "           (Microsoft Edge, unless overridden with --agent)",
        "    --pathname=<pathname>",
        "           Download file to specified pathname",
        "    --primary",
        "           Try to fetch from the IERS URL before the cache URL",
        "    -q     Do not write to STDOUT or STDERR, just exit with 0 or 1",
        "    --retry=<N>",
        "           Upon fetch failure, try again up to N times (default 0).",
        "    --show-url",
        "           Print source URL before printing destination pathname",
    ), "\n");
    return 1;
}

=head1 NAME

C<tai-download-leapseconds> -- download the IETF leapseconds file.

=head1 SYNOPSIS

    tai-download-leapseconds http://my.server/foo/leaps.list http://other.server/leaps.list
    tai-download-leapseconds --help
    tai-download-leapseconds --quiet --pathname=/etc/leap-seconds.list
    tai-download-leapseconds --show-url

=head1 DESCRIPTION

C<tai-download-leapseconds> iterates through a list of URLs and attempts to
download the IETF leapseconds list file, saving it by default to a location
where C<Time::TAI::Simple> knows to look for it.

By default it writes the pathname of the downloaded file to STDOUT upon
success, or an error message to STDERR on failure.

If the user wishes to specify URLs where C<tai-download-leapseconds> should
look first, any number of URLs may be specified as command line arguments, 
which will be checked in order.

These default behaviors may be controlled via some options:

    -h          Describe available options
    --help      Same as -h
    --add-agent=<string>
                Add the specified User-Agent string to the internal list
    --add-agent=\"<string>|<string>|...\"
                Add the specified User-Agent strings to the internal list
    --agent=<string>
                Use the specified User-Agent string
    --churn-agent
                On failure, pick a random User-Agent string for next try
                (Most useful when --retry=N is set to N > 1)
                (Does not work with --force-edge)
    --debug
                Show annoying descriptions of what it is doing (ignores -q)
    --force-edge
                Always use the first User-Agent string in the list
                (Microsoft Edge, unless overridden with --agent)
    --pathname=<pathname>
                Specify the pathname to which the file is saved.
    --primary
                Try to fetch from the IERS URL before the cache URL
    --retry=<N>
                Upon fetch failure, try again up to N times (default 0).
    --retry-delay=<N>
                When --retry is set, sleep N seconds between tries (default 0.5).
    --show-url  Write to STDOUT the URL from which the file was downloaded.
                (Before pathname is written to STDOUT, on a different line.)
    -q          Do not write pathname to STDOUT or error messages to STDERR.

=head1 ABOUT URLS

At the time of this writing, C<tai-download-leapseconds> first tries to download
the leapseconds list from the module author's own server, B<which under normal
circumstances should fail> (with an HTTP C<404> reply code).  When it is unable
to retrieve the list from this location, it will attempt to download the list
from the IETF's server at L<https://www.ietf.org/timezones/data/leap-seconds.list>.

The reason for doing it this way is to allow workarounds should the IETF suffer
infrastructure failure.  If the IETF changes the location of their official list
without setting up a redirect, or if their servers go down for an extended period
of time, the module author can set up an HTTP C<302> redirect to the new official
leapsecond location, or provide a copy of the file directly.

Administrators who do not feel comfortable depending on some random guy's server
should maintain their own redirect or leapsecond list file for their organization
and pass the URL of this resource to C<tai-download-leapseconds> as an argument,
or just maintain each server's C</etc/leap-seconds.list> themselves and not use
C<tai-download-leapseconds> at all.

=head1 SEE ALSO

L<Time::TAI::Simple>

=head1 AUTHOR

TTK Ciar, <ttk[at]ciar[dot]org>

=head1 COPYRIGHT AND LICENSE

Copyright 2014-2015 by TTK Ciar

This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

=cut
