#!/usr/bin/perl  

=head1 NAME

md-request - 多线程多地址非阻塞的下载工具

=head1 DESCRIPTION

本工具支持从多个地址下载同一个文件, 并且是单线程事件驱动的分块下载.

=head1 EXAMPLE

例如, 下载最新的 Perl 的版本:

    $ md-request -a http://www.perl.com/CPAN/src/latest.tar.gz

=head1 AUTHOR

fukai <iakuf@163.com>

=cut 

use strict;
use AnyEvent;
use AE;
use AnyEvent::MultiDownload;
use Getopt::Long;
use Smart::Comments;

my $progname = $0;
$progname =~ s,.*/,,;    # only basename left in progname
$progname =~ s,.*\\,, if $^O eq "MSWin32";
$progname =~ s/\.\w*$//; # strip extension if any

#parse option
my (@urls, $dest);

GetOptions(
    'a=s', \@urls, 
    '-d', \$dest
);
unless (@urls) {
    usage();
}

$SIG{INT} = sub { die "Interrupted\n"; };

$| = 1;

my ($filename) = $urls[0] =~ /([^\/]+)$/;
my $start_t = time();
 
my $cv = AE::cv;
my $MultiDown = AnyEvent::MultiDownload->new(
    url     => shift @urls,
    mirror  => \@urls,
    content_file => $dest || $filename,
    seg_size  => 1 * 1024 * 1024, # 1M
    on_finish => sub {
        my $len = shift;
        my $dur = time - $start_t;
        my $speed = fbytes($len/$dur) . "/sec";
        print STDERR "Finished. " . fbytes($len) . " received in $dur seconds ($speed)\n";
        $cv->send;
    },
    on_error => sub {
        my $error = shift;
        print STDERR "Transfer aborted, $error\n";
        $cv->send;
    }
)->multi_get_file;

$cv->recv;

sub usage {
    die "Usage: $progname [-a] <url>\n";
}

sub fbytes {
    my $n = int(shift);
    if ($n >= 1024 * 1024) {
        return sprintf "%.3g MB", $n / (1024.0 * 1024);
    }
    elsif ($n >= 1024) {
        return sprintf "%.3g KB", $n / 1024.0;
    }
    else {
        return "$n bytes";
    }
}

#sub fduration {
#    use integer;
#    my $secs = int(shift);
#    my $hours = $secs / (60*60);
#    $secs -= $hours * 60*60;
#    my $mins = $secs / 60;
#    $secs %= 60;
#    if ($hours) {
#        return "$hours hours $mins minutes";
#    }
#    elsif ($mins >= 2) {
#        return "$mins minutes";
#    }
#    else {
#        $secs += $mins * 60;
#        return "$secs seconds";
#    }
#}
