#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use Pod::Usage;
use Amon2::Setup::Flavor::Basic;
use Amon2::Setup::VC::Git;
use Cwd ();
use Plack::Util;
use File::Find ();
use File::Spec ();

my @flavors;
my $vc = 'Git';
GetOptions(
    'help'           => \my $help,
    'list-flavors|l' => \my $list_flavors,
    'flavor=s@'      => \@flavors,
    'vc=s'           => \$vc,
    'version'        => \my $version,
) or pod2usage(0);
if ($version) {
    require Amon2;
    print "Perl: $]\n";
    print "Amon2: $Amon2::VERSION\n";
    exit(0);
}
list_flavors() if $list_flavors;
pod2usage(1) if $help;
push @flavors, 'Basic' if @flavors == 0;
@flavors = map { split /,/, $_ } @flavors;

&main;exit;

sub main {
    my $module = shift @ARGV or pod2usage(0);
       $module =~ s!-!::!g;

    # $module = "Foo::Bar"
    # $dist   = "Foo-Bar"
    # $path   = "Foo/Bar"
    my @pkg  = split /::/, $module;
    my $dist = join "-", @pkg;
    my $path = join "/", @pkg;

    mkdir $dist or die "Cannot mkdir '$dist': $!";
    chdir $dist or die $!;

    my @flavor_classes;
    my @flavor_instances;
    for my $flavor (@flavors) {
        my $flavor_class = load_flavor($flavor);
        push @flavor_classes, $flavor_class;

        print "-- Running flavor: $flavor --\n";

        my $cwd = Cwd::getcwd(); # save cwd
            {
                my $flavor = $flavor_class->new(module => $module);
                   $flavor->run;
                push @flavor_instances, $flavor;
            }
        chdir($cwd);
    }

	{
		$vc = Plack::Util::load_class($vc, 'Amon2::Setup::VC');
		$vc = $vc->new();
		$vc->do_import();
	}

    for my $flavor_class (@flavor_classes) {
        if ($flavor_class->can('call_trigger')) {
            $flavor_class->call_trigger('AFTER_VC');
        }
    }

    for my $flavor (@flavor_instances) {
        if ($flavor->can('show_banner')) {
            $flavor->show_banner();
        }
    }
}

sub load_flavor {
    my $flavor_name = shift;

    my $flavor_class = $flavor_name =~ s/^\+// ? $flavor_name : "Amon2::Setup::Flavor::$flavor_name";
    eval "use $flavor_class; 1" or die "Cannot load $flavor_class: $@";

    return $flavor_class;
}

sub list_flavors {

    my $prefix = "Amon2::Setup::Flavor";

    my $dir = File::Spec->catdir(split /::/, $prefix);

    my @results;
    my %seen;
    foreach my $base(map { File::Spec->catdir($_, $dir) } @INC) {
        next unless -d $base;

        File::Find::find({
                wanted => sub {
                    return unless -r;
                    my $name = File::Spec->abs2rel($_, $base);
                    $name =~ s/\.pm$// or return;

                    $seen{$name}++ and return;

                    push @results, join '::', File::Spec->splitdir($name);
                },
                no_chdir => 1,
            }, $base);
    }

    for my $moniker (sort @results) {
        my $module = eval {
            Plack::Util::load_class($moniker, $prefix);
        };
        # extract short description
        my $content = do {
            open my $fh, "<", $INC{join("/", split "::", $module).".pm"};
            local $/;
            <$fh>;
        };
        my($description) = $content =~ m{
            ^=head1 \s+ NAME
            \s+
            \Q$module\E \s+ - \s+ ([^\n]+)
        }xms;
        if (defined $description) {
            print $moniker, " - ", $description, "\n";
        }
        else {
            print $moniker, "\n";
        }
    }

    exit;
}

__END__

=head1 NAME

amon2-setup.pl - setup script for amon2

=head1 SYNOPSIS

    % amon2-setup.pl MyApp

        --flavor=Basic      basic flavour (default)
        --flavor=Lite       Amon2::Lite flavour (need to install)
        --flavor=Minimum    minimalistic flavour for benchmarking
        --flavor=Standalone CPAN uploadable web application(EXPERIMENTAL)

        --vc=Git         setup the git repository (default)

        --list-flavors (or -l) Shows the list of flavors installed

        --help   Show this help

=head1 DESCRIPTION

This is a setup script for Amon2.

amon2-setup.pl is highly extensible. You can write your own flavor.

=head1 HINTS

You can specify C<< --flavor >> option multiple times. For example, you can
type like following:

    % amon2-setup.pl --flavor=Basic --flavor=Teng MyApp

    % amon2-setup.pl --flavor=Teng,Basic MyApp

Second flavor can overwrite files generated by first flavor.

=head1 AUTHOR

Tokuhiro Matsuno

=cut