package Dist::Zilla::Plugin::ModuleBuildTiny;
$Dist::Zilla::Plugin::ModuleBuildTiny::VERSION = '0.015';
use Moose;
with qw/
	Dist::Zilla::Role::BuildPL
	Dist::Zilla::Role::TextTemplate
	Dist::Zilla::Role::PrereqSource
	Dist::Zilla::Role::FileGatherer
	Dist::Zilla::Role::MetaProvider
/;

use Dist::Zilla 4.300039;
use Module::Metadata;
use Moose::Util::TypeConstraints 'enum';
use MooseX::Types::Perl qw/StrictVersionStr/;
use List::Util 1.33 qw/first any/;

has version_method => (
	is      => 'ro',
	isa     => enum(['installed', 'conservative']),
	default => 'conservative',
);

has has_pl => (
	is      => 'ro',
	isa     => 'Bool',
	lazy    => 1,
	default => sub {
		my $self = shift;
		return any { $_->name =~ /^lib\/.*\.PL$/ } @{ $self->zilla->files };
	},
);

has has_xs => (
	is      => 'ro',
	isa     => 'Bool',
	lazy    => 1,
	default => sub {
		my $self = shift;
		return any { $_->name =~ /^lib\/.*\.xs$/ } @{ $self->zilla->files };
	},
);

has static => (
	is      => 'ro',
	isa     => enum([qw/no yes auto/]),
	default => 'no',
);

has version => (
	is      => 'ro',
	lazy    => 1,
	isa     => StrictVersionStr,
	default => sub {
		my $self = shift;
		if ($self->version_method eq 'installed') {
			return Module::Metadata->new_from_module('Module::Build::Tiny')->version->stringify;
		}
		elsif ($self->has_pl) {
			return '0.039';
		}
		elsif ($self->has_xs) {
			return '0.036';
		}
		return '0.034'; # _build_params format
	},
);

has minimum_perl => (
	is      => 'ro',
	isa     => StrictVersionStr,
	lazy    => 1,
	default => sub {
		my $self = shift;
		my $prereqs = $self->zilla->prereqs->cpan_meta_prereqs;
		my $reqs = $prereqs->merged_requirements([ qw/configure build test runtime/ ], ['requires']);
		return $reqs->requirements_for_module('perl') || '5.006';
	},
);

my $template = <<'BUILD_PL';
# This Build.PL for {{ $dist_name }} was generated by {{ $plugin_title }}.
use strict;
use warnings;

use {{ $minimum_perl }};
use Module::Build::Tiny{{ $version ne 0 && " $version" }};
Build_PL();
BUILD_PL

sub register_prereqs {
	my ($self) = @_;

	$self->zilla->register_prereqs({ phase => 'configure' }, 'Module::Build::Tiny' => $self->version);

	return;
}

sub can_static {
	my $self = shift;
	return !$self->has_pl && !$self->has_xs;
}

sub metadata {
	my $self = shift;
	my $static = $self->static eq 'yes' || $self->static eq 'auto' && $self->can_static;
	return $static ? { x_static_install => 1 } : ();
}

sub gather_files {
	my ($self) = @_;

	if (my $file = first { $_->name eq 'Build.PL' } @{$self->zilla->files})
	{
		# if it's another type, some other plugin added it, so it's better to
		# error out and let the developer sort out what went wrong.
		if ($file->isa('Dist::Zilla::File::OnDisk'))
		{
			$self->log('replacing existing Build.PL found in repository');
			$self->zilla->prune_file($file);
		}
	}

	require Dist::Zilla::File::InMemory;
	my $file = Dist::Zilla::File::InMemory->new({
		name => 'Build.PL',
		content => $template,    # template evaluated later
	});

	$self->add_file($file);
	return;
}

sub setup_installer {
	my ($self, $arg) = @_;

	confess 'Module::Build::Tiny is currently incompatible with dynamic_config' if $self->zilla->distmeta->{dynamic_config};

	for my $map (map { $_->share_dir_map } @{$self->zilla->plugins_with(-ShareDir)}) {
		$self->log_fatal('Unsupported use of a module sharedir') if exists $map->{module};
		$self->log_fatal('Sharedir location must be share/') if defined $map->{dist} and $map->{dist} ne 'share';
	}

	my $file = first { $_->name eq 'Build.PL' } @{$self->zilla->files};
	my $content = $file->content;

	$content = $self->fill_in_string($content, {
			version      => $self->version,
			minimum_perl => $self->minimum_perl,
			dist_name    => $self->zilla->name,
			plugin_title => ref($self) . ' ' . ($self->VERSION || '<self>'),
		});

	$self->log_debug([ 'updating contents of Build.PL in memory' ]);
	$file->content($content);

	return;
}

__PACKAGE__->meta->make_immutable;
no Moose::Util::TypeConstraints;
no Moose;
1;

# ABSTRACT: Build a Build.PL that uses Module::Build::Tiny


# vim: set ts=4 sw=4 noet nolist :

__END__

=pod

=encoding UTF-8

=head1 NAME

Dist::Zilla::Plugin::ModuleBuildTiny - Build a Build.PL that uses Module::Build::Tiny

=head1 VERSION

version 0.015

=head1 DESCRIPTION

This plugin will create a F<Build.PL> for installing the dist using L<Module::Build::Tiny|Module::Build::Tiny>.

=head1 ATTRIBUTES

=head2 version

B<Optional:> Specify the minimum version of L<Module::Build::Tiny|Module::Build::Tiny> to depend on.

Defaults to the version determined by C<version_method>.

=head2 version_method

This attribute determines how the default minimum perl is detected. It has two possible values:

=over 4

=item * installed

This will give the version installed on the author's perl installation.

=item * conservative

This will return a heuristically determined minimum version of MBT.

=back

=head2 minimum_perl

B<Optional:> Specify the minimum version of perl to require in the F<Build.PL>.

This is normally taken from dzil's prereq metadata.

=head2 static

This is an option to set the B<HIGHLY EXPERIMENTAL> C<x_static_install>
metadata field. B<DO NOT USE THIS OPTION> if you are not involved in its
testing with the Perl Toolchain Gang.

It has three possible values:

=over 4

=item * no

No extra metadata is added. This is the default setting.

=item * yes

Sets C<x_static_install = 1> in metadata.

=item * auto

Sets C<x_static_install = 1> in metadata if the distribution appears to be
compatible - presently only the existence of F<.PL> and F<.xs> files are
checked.

=back

=head1 AUTHOR

Leon Timmermans <fawaka@gmail.com>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2011 by Leon Timmermans.

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

=cut