#! perl ## no critic (PerlMinimumVersion)

use warnings;
use strict;
use 5.010;
use IO::Handle             qw(                       );
use List::Util             qw( first                 );
use List::MoreUtils        qw( indexes uniq          );
use File::Slurp            qw( read_file             );
use File::ShareDir    1.00 qw( module_file dist_file );
use Getopt::Long           qw( GetOptions            );
use Pod::Usage             qw( pod2usage             );
use English                qw( -no_match_vars        );
use CPAN::Mini::Devel 0.03 qw(                       );
use LWP::UserAgent         qw(                       ); 
use File::Spec::Functions  qw( catdir                );

our $VERSION = '1.110';
$VERSION = eval $VERSION;

sub filters;
sub usage;
sub version;

STDOUT->autoflush(1);
STDERR->autoflush(1);

my (@dists, @modules, @files, @add_files);
my $verbose = 1;
my $force = 0;
my $cpan = 'http://cpan.hexten.net/';
my $minicpan = 'C:\minicpan';

my $result = GetOptions(
            "cpan=s"     => \$cpan,
            "minicpan=s" => \$minicpan,
            "dist=s"     => \@dists,
            "module=s"   => \@modules,      
            "file=s"     => \@files,      
            "add_file=s" => \@add_files,
            "verbose!"   => \$verbose,
            "force!"     => \$force,
			"help|?"     => sub { pod2usage(-exitstatus => 1, -verbose => 0); },
			"man"        => sub { pod2usage(-exitstatus => 1, -verbose => 2); },
			"usage"      => sub { usage(); },
			"version"    => sub { version(); }
		);
		
$result or usage();

my @input;

foreach my $dist (@dists) {
	my @regex_file = read_file( dist_file( $dist, 'minicpan_filters.txt' ) );
	push @input, @regex_file;
}

foreach my $module (@modules) {
	my @regex_file = read_file( module_file( $module, 'minicpan_filters.txt' ) );
	push @input, @regex_file;
}

foreach my $file (@files) {
	my @regex_file = read_file( $file );
	push @input, @regex_file;
}

# Delete comments
chomp @input;
my @regex_list = uniq grep { $_ !~ m{\A\s*\z|\A\s*#} } @input;

if ($#regex_list < 0) {
	usage(<<'EOF');
No files to download.
One or more of --file, --dist, or --module must be used.
EOF
}

say 'Updated: ', scalar localtime;

CPAN::Mini::Devel->update_mirror(
	remote       => $cpan,
	local        => $minicpan,
	trace        => $verbose,
	force        => $force,
	path_filters => [ sub { filters( $_[0] ); } ] );

my $ua;
foreach my $file_to_add (@add_files) {
	$ua //= LWP::UserAgent->new(env_proxy => 1, agent => "minicpan_pdwix/$VERSION ");

	my $l1 = substr $file_to_add, 0, 1;
	my $l2 = substr $file_to_add, 0, 2;

	my $url = "${cpan}author/id/$l1/$l2/$file_to_add";
	my $target = catfile( $minicpan, qw( author id ), $l1, $l2, $file_to_add ); 
	print "Downloading URL $url to $target\n";
	$ua->mirror( $url, $target );
}
	
say 'Finished: ', scalar localtime;

exit 0;

sub filters {
	my $dist = shift;

	my $result = first { $dist =~ m{$_} } @regex_list;
	
	return ( defined $result ? 0 : 1 );
}

sub version {
	my $version = $VERSION->stringify();

	print <<"EOF";
This is $PROGRAM_NAME, version $VERSION, a minicpan script 
for Perl::Dist::WiX and subclasses.

Copyright 2009 Curtis Jewell.

This script may be copied only under the terms of either the Artistic License
or the GNU General Public License, which may be found in the Perl 5 
distribution or the distribution containing this script.
EOF

	exit(1);
	
}

sub usage {
	my $error = shift;

	print "Error: $error\n\n" if (defined $error);

	print <<"EOF";
This is $PROGRAM_NAME, version $VERSION, a minicpan script 
for Perl::Dist::WiX and subclasses.

Usage: $PROGRAM_NAME [ --dist <distribution> ] [ --module <module> ]
                     [ --file <file> ] [ --cpan <URL> ] [ --[no]force ]
                     [ --minicpan <filespec> ] [ --[no]verbose ]
                     [ --help ] [ --usage ] [ --man ] [ --version ] [ -? ]

For more assistance, run $PROGRAM_NAME --help.
EOF

	exit(1);	
}

__END__

=head1 NAME

minicpan_pdwix - a minicpan script for Perl::Dist::WiX and subclasses.

=head1 VERSION

This document describes minicpan_pdwix version 1.000.

=head1 DESCRIPTION

This creates a minicpan for L<Perl::Dist::WiX> and subclasses to 
use that contains the minimum files required to make a perl 
distribution.

=head1 SYNOPSIS

  minicpan_pdwix [ --dist <distribution> ] [ --module <module> ]
                 [ --file <file> ] [ --cpan <URL> ] [ --[no]force ]
                 [ --minicpan <dir> ] [ --[no]verbose ]
                 [ --help ] [ --usage ] [ --man ] [ --version ] [ -?]
				 
  Options:
    --dist <dist>     Loads a list to download from the named distribution.
    --module <module> Loads a list to download from the named module.
    --file <file>     Loads a list to download from the named file.	
    --cpan <URL>      Specifies the CPAN mirror to download to.
                      Defaults to http://cpan.hexten.net/.
    --minicpan <dir>  Specifies the directory to download to.
                      Defaults to C:\minicpan\.

    --verbose         Lists the files as they are downloaded. (default)
    --noverbose       Does not list the files as they are downloaded.
	
    --force           Forces rescanning even if index files are not updated.
    --noforce         Does not force rescanning of minicpan. (default)

    --usage           Gives a minimum amount of aid and comfort.
    --help            Gives aid and comfort.
    -?                Gives aid and comfort.
    --man             Gives maximum aid and comfort.	
	
    --version         Gives the name, version and copyright of the script.
	
=head1 OPTIONS

=over

=item B<--dist>

Loads a list of regular expressions that specify which files to download 
from the file minicpan_filters.txt in the directory File::ShareDir uses 
for the named distribution.

=item B<--module>

Loads a list of regular expressions that specify which files to download 
from the file minicpan_filters.txt in the directory File::ShareDir uses 
for the named module.

=item B<--file>

Loads a list of regular expressions that specify which files to download 
from the named file.

=item B<--cpan>

Specifies the CPAN mirror to use.

Defaults to L<http://cpan.hexten.net/>.

=item B<--minicpan>

Specifies the location to download the minicpan.

Defaults to C<C:\minicpan\>.

=item B<--verbose>/B<--noverbose>

Specifies whether the list of files downloaded should be printed or not.

Defaults to B<--verbose>.

=item B<--force>/B<--noforce>

Specifies whether the index files should be rescanned even if they were not
updated.  This is useful when the list of files to download has been changed.

Defaults to B<--noforce>.

=item B<--usage>

Print a brief usage message and exits.

=item B<--help> or B<-?>

Print a short help message and exits.

=item B<--man>

Prints the POD documentation contained in the script and exits.

=item B<--version>

Prints the script name, version, and copyright and exits.

=back

=head1 CONFIGURATION

No environment variables are used during the execution of this script 
that the modules used do not already use.

The --dist and --module options use File::ShareDir to get a file named
minicpan_filters.txt from the root directory of the named options.

The --file option names a file to load.

The files loaded by the options mentioned above contain a list of regular 
expressions that define files to download, as shown in the example file 
below:

	# Downloads 4 files.
	
	/MBARBON/Wx-\d
	/MDOOTSON/Wx-Perl-ProcessStream-
	/(?:GARU|SZABGAB)/Padre-\d
	/AZAWAWI/Padre-Plugin-Perl6-

There are no options given by default, and lines containing only whitespace, 
or that are empty, or whose first non-whitespace character is a C<#> are 
disregarded. 

=head1 DEPENDENCIES

Perl 5.10.0 is the mimimum version of perl that this script will run on.

Other modules that this script depends on are L<IO::Handle>, L<List::Util>, 
L<List::MoreUtils>, L<File::ShareDir> 1.00, L<File::Slurp>, L<Getopt::Long>,
L<Pod::Usage>, L<English>, L<CPAN::Mini> 0.576, and L<CPAN::Mini::Devel> 
0.03.
 
=head1 SUPPORT

No support is provided for this script.

=head1 AUTHOR

Curtis Jewell, E<lt>csjewell@cpan.orgE<gt>

=head1 COPYRIGHT & LICENSE

Copyright 2009 Curtis Jewell.

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

The full text of the license can be found in the
LICENSE file included with this distribution.

=cut
