#!/usr/bin/perl
# -*- cperl -*-
# ------------------------------------------------------------------------------
#   setup.pl is in the public domain.
#   written by PHO.
#
#   v1.0 / 2006-01-28
# ------------------------------------------------------------------------------
use strict;
use warnings;
sub req ($;$);
sub opt ($;$);
# ------------------------------------------------------------------------------
# Example:
#
#   [Requirement]
#   req 'LWP::UserAgent'; # any version of LWP::UserAgent
#   req 'Data::Dumper' => 1.1; # Data::Dumper 1.1 or later
#
#   [Optional]
#   opt 'CGI::Fast';
#   opt 'CGI' => 3.0;
#
# ------------------------------------------------------------------------------
req 'URI';
req 'URI::QueryParam';
req 'HTTP::Date';
req 'CGI';
opt 'CGI::Fast';
req 'DBI';
req 'DBD::SQLite';
req 'File::Spec';
req 'HTTP::Cookies';
req 'HTTP::Status';
req 'Digest::MD5';
req 'Encode';
req 'XML::RSS';
req 'Time::Zone';
req 'Carp';

# ------------------------------------------------------------------------------
# Code below is not supposed to be modified.
# ------------------------------------------------------------------------------
my @unavail_req;
my @unavail_opt;

sub req ($;$) {
    check(req => @_);    
}

sub opt ($;$) {
    check(opt => @_);
}

sub check {
    my ($which, $mod, $ver) = @_;
    my $unavail = ($which eq 'req' ? \@unavail_req : \@unavail_opt);

    local $| = 1;
    if ($ver) {
	print "checking if $mod >= $ver is available... ";
    }
    else {
	print "checking if $mod is available... ";
    }
    
    eval qq{
	use $mod;
    };
    if ($@) {
	if ($ver) {
	    print "no (not available)\n";
	}
	else {
	    print "no\n$@\n";
	}
	push @$unavail, $mod;
    }
    else {
	if ($ver) {
	    my $VER = eval("\$${mod}::VERSION");
	    if ($VER >= $ver) {
		print "yes ($VER)\n";
	    }
	    else {
		print "no ($VER)\n";
		push @$unavail, $mod;
	    }
	}
	else {
	    print "yes\n";
	}
    }
}

my $cpan;
sub check_for_cpans () {
    $cpan and return;
    
    $cpan = {};
    
    eval qq{
        use CPAN;
    };
    $@ or $cpan->{cpan} = 1;

    eval qq{
	use CPANPLUS;
    };
    $@ or $cpan->{cpanplus} = 1;
}

sub install {
    my ($req, @mods) = @_;
    check_for_cpans;

    my $default;
    if ($cpan->{cpan} and $cpan->{cpanplus}) {
	print "Both CPAN.pm and CPANPLUS.pm are available.\n";
	print "What do you want to make me do?\n";
	print "\n";
	print "  [1] Install them with CPAN.pm\n";
	print "  [2] Install them with CPANPLUS.pm\n";
	if ($req) {
	    print "  [3] Abort the setup.\n";
	}
	else {
	    print "  [3] Ignore those modules.\n";
	}
	$default = 2;
    }
    elsif ($cpan->{cpan}) {
	print "CPAN.pm is available.\n";
	print "What do you want to make me do?\n";
	print "\n";
	print "  [1] Install them with CPAN.pm\n";
	if ($req) {
	    print "  [2] Abort the setup.\n";
	}
	else {
	    print "  [2] Ignore those modules.\n";
	}
	$default = 1;
    }
    elsif ($cpan->{cpanplus}) {
	print "CPANPLUS.pm is available.\n";
	print "What do you want to make me do?\n";
	print "\n";
	print "  [1] Install them with CPANPLUS.pm\n";
	if ($req) {
	    print "  [2] Abort the setup.\n";
	}
	else {
	    print "  [2] Ignore those modules.\n";
	}
	$default = 1;
    }
    else {
	print "Neither CPAN.pm nor CPANPLUS.pm are available, so I can't\n";
	print "install them automatically for you.\n";
	$req and exit 1;
	return;
    }

    local $| = 1;
    while (1) {
	print "\n";
	print "Please enter the number [$default]: ";
	my $choice = <>;
	chomp $choice;
	length $choice or $choice = $default;

	if ($cpan->{cpan} and $cpan->{cpanplus}) {
	    if ($choice == 1) {
		cpan_install(@mods);
		last;
	    }
	    elsif ($choice == 2) {
		cpanplus_install(@mods);
		last;
	    }
	    elsif ($choice == 3) {
		$req and exit 1;
		return;
	    }
	}
	else {
	    if ($choice == 1) {
		if ($cpan->{cpan}) {
		    cpan_install(@mods);
		}
		elsif ($cpan->{cpanplus}) {
		    cpanplus_install(@mods);
		}
		last;
	    }
	    elsif ($choice == 2) {
		$req and exit 1;
		return;
	    }
	}
    }
}

sub cpan_install {
    my @mods = @_;
    
    foreach my $mod (@mods) {
	CPAN::Shell->install($mod);
    }
}

sub cpanplus_install {
    my @mods = @_;

    foreach my $mod (@mods) {
	CPANPLUS::install($mod);
    }
}

if (@unavail_req) {
    print "\n";
    print "The following modules are unavailable, which are required by this program:\n";
    foreach (@unavail_req) {
	print "    $_\n";
    }
    print "\n";
    install(1, @unavail_req);
}

if (@unavail_opt) {
    print "\n";
    print "The following modules are unavailable, which are optionally wanted by this program:\n";
    foreach (@unavail_opt) {
	print "    $_\n";
    }
    print "\n";
    install(0, @unavail_opt);
}

print "\n";
print "Setup completed.\n";
