package Dist::Banshee::MakeMaker::Simple;
$Dist::Banshee::MakeMaker::Simple::VERSION = '0.002';
use strict;
use warnings;

use Exporter 5.57 'import';
our @EXPORT_OK = qw/makemaker_simple/;

use Carp 'croak';
use version;

sub normalize_eumm_versions {
	my ($prereqs) = @_;
	for my $v (values %$prereqs) {
		if (version::is_strict($v)) {
			my $version = version->parse($v);
			if ($version->is_qv) {
				if ((() = $v =~ /\./g) > 1) {
					$v =~ s/^v//;
				}
				else {
					$v = $version->numify;
				}
			}
		}
	}
	return $prereqs;
}
 
sub dump_as {
	my ($ref, $name) = @_;
	require Data::Dumper;
	my $dumper = Data::Dumper->new( [ $ref ], [ $name ] );
	$dumper->Sortkeys( 1 );
	$dumper->Indent( 1 );
	$dumper->Useqq( 1 );
	return $dumper->Dump;
}

sub share_dir_code {
	my ($share_dir_map) = @_;

	my $share_dir_code = {};

	if ( keys %$share_dir_map ) {
		my $preamble = <<'PREAMBLE';
use File::ShareDir::Install;
$File::ShareDir::Install::INCLUDE_DOTFILES = 1;
$File::ShareDir::Install::INCLUDE_DOTDIRS = 1;
PREAMBLE

		if ( my $dist_share_dir = $share_dir_map->{dist} ) {
			$dist_share_dir = quotemeta $dist_share_dir;
			$preamble .= qq{install_share dist => "$dist_share_dir";\n};
		}

		if ( my $mod_map = $share_dir_map->{module} ) {
			for my $mod ( sort keys %$mod_map ) {
				my $mod_share_dir = quotemeta $mod_map->{$mod};
				$preamble .= qq{install_share module => "$mod", "$mod_share_dir";\n};
			}
		}

		my $postamble = qq{\n\{\npackage\nMY;\nuse File::ShareDir::Install qw(postamble);\n\}\n};
		return ("\n$preamble\n", $postamble);
	}

	return ('', '');
}
 
sub makemaker_simple {
	my ($meta, $files, $options) = @_;
 
	(my $name = $meta->name) =~ s/-/::/g;
 
	my @exe_files = grep { m{\A ( bin | script ) / }x } keys %{ $files };
	croak "Can't install files with whitespace in their names" if grep { /\s/ } @exe_files;
 
	my %test_dirs;
	for my $file (keys %{ $files }) {
		next unless $file =~ m{\At/.+\.t\z};
		(my $dir = $file) =~ s{/[^/]+\.t\z}{/*.t}g;

		$test_dirs{ $dir } = 1;
	}
 
	my $prereqs = $meta->effective_prereqs;
	my $perl_prereq = $prereqs->requirements_for(qw(runtime requires))
		->clone
		->add_requirements($prereqs->requirements_for(qw(configure requires)))
		->add_requirements($prereqs->requirements_for(qw(build requires)))
		->add_requirements($prereqs->requirements_for(qw(test requires)))
		->as_string_hash->{perl};
 
	$perl_prereq = version->parse($perl_prereq)->numify if $perl_prereq;
 
	my $prereqs_dump = sub {
		normalize_eumm_versions(
			$prereqs->requirements_for(@_)
							->clone
							->clear_requirement('perl')
							->as_string_hash
		);
	};
 
	my %require_prereqs = map {
		$_ => $prereqs_dump->($_, 'requires');
	} qw(configure build test runtime);
 
	# EUMM may soon be able to support this, but until we decide to inject a
	# higher configure-requires version, we should at least warn the user
	# https://github.com/Perl-Toolchain-Gang/ExtUtils-MakeMaker/issues/215
	my $eumm_version = $meta->effective_prereqs->requirements_for('configure', 'requires')->requirements_for_module('ExtUtils::MakeMaker') || 0;
	foreach my $phase (qw(configure build test runtime)) {
		for my $module (keys %{ $require_prereqs{$phase} }) {
			my $version = $require_prereqs{$phase}{$module};
			if (defined $version && !version::is_lax($version)) {
				croak "found version range in $phase prerequisites, which ExtUtils::MakeMaker cannot parse (must specify eumm_version of at least 7.1101): $module $version";
			}
		}
	}
 
	my %write_makefile_args = (
		DISTNAME => $meta->name,
		NAME     => $name,
		AUTHOR   => join(q{, }, $meta->authors),
		ABSTRACT => $meta->abstract,
		VERSION  => $meta->version,
		LICENSE  => ($meta->license)[0],
		@exe_files ? ( EXE_FILES => [ sort @exe_files ] ) : (),
 
		CONFIGURE_REQUIRES => $require_prereqs{configure},
		keys %{ $require_prereqs{build} } ? ( BUILD_REQUIRES => $require_prereqs{build} ) : (),
		keys %{ $require_prereqs{test} } ? ( TEST_REQUIRES => $require_prereqs{test} ) : (),
		PREREQ_PM          => $require_prereqs{runtime},
 
		test => { TESTS => join q{ }, sort keys %test_dirs },
	);
 
	$write_makefile_args{MIN_PERL_VERSION} = $perl_prereq if $perl_prereq;
 
	my $WriteMakefileArgs = dump_as(\%write_makefile_args, '*WriteMakefileArgs');
 
	my $fallback
		= normalize_eumm_versions(
			$meta->effective_prereqs->merged_requirements
			->clone
			->clear_requirement('perl')
			->as_string_hash
		);
	my $fallback_prereqs = dump_as($fallback, '*FallbackPrereqs');
	my $generated_by = __PACKAGE__;

	my ($preamble, $postamble) = share_dir_code($options->{share});

	my $content = <<"EOF";
# This file was automatically generated by $generated_by.
use strict;
use warnings;

@{[ $perl_prereq ? qq[use $perl_prereq;] : '' ] }

use ExtUtils::MakeMaker $eumm_version;
$preamble
my $WriteMakefileArgs

my $fallback_prereqs

unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
  delete \$WriteMakefileArgs{TEST_REQUIRES};
  delete \$WriteMakefileArgs{BUILD_REQUIRES};
  \$WriteMakefileArgs{PREREQ_PM} = \\\%FallbackPrereqs;
}

delete \$WriteMakefileArgs{CONFIGURE_REQUIRES}
  unless eval { ExtUtils::MakeMaker->VERSION(6.52) };

WriteMakefile(%WriteMakefileArgs);
$postamble
EOF
 
	chomp $content;
	return $content;
}

1;
