package Module::Make;
use 5.006001;
use strict;
use warnings;
use Module::Make::Base -base;
our $VERSION = '0.01';

const maker_class => 'Module::Make::Maker';
field 'src_dir';

sub import {
    my $class = shift;
    my $flag = shift || '';
    my $package = caller;
    no strict 'refs';
    if ($flag eq 'new') {
        $class->new->new_environment(@ARGV);
        exit;
    }
    elsif ($flag eq 'update') {
        $class->new->update_environment(@ARGV);
        exit;
    }
}

sub new_environment {
    my $self = shift;

    # Check to make sure the cli args are sane
    $self->sanity_check_new_cli_args(@_);

    # Prompt user to create the target directory
    $self->get_src_dir;

    # Make appropriate directories
    $self->make_src_dir;

    # Change to src dir
    $self->chdir_src;

    # Write a `config.yaml` file.
    $self->create_config_yaml_file;
    
    # Generate mininal Makefile
    $self->create_new_makefile;
    
    # sleep 1
    # touch .stamps/new_environment

    # tell user to now edit the `config.yaml` file
}

sub update_environment {
    die "Can't update existing Module::Make environment yet";
}

sub sanity_check_new_cli_args {
    my $self = shift;
    my $dir = io->dir(shift || '.');
    die "Unknown args '@_' to Module::Make=new\n" if @_;
    $dir = $self->check_new_dir_path($dir);
    $self->src_dir($dir);
}

sub get_src_dir {
    my $self = shift;
    my $dir = $self->src_dir;
    return if $dir->exists;
    while (1) {
        return if $self->prompt_yn("Create $dir", 'Yn') eq 'y';
        my $path = $self->prompt_path("Enter a new module dist path:");
        $dir = io->dir($path);
        $dir = $self->check_new_dir_path($dir);
    }
}

sub make_src_dir {
    my $self = shift;
    my $dir = $self->src_dir;
    if ($dir->exists) {
        print "Using '$dir' for new environment.\n";
        return;
    }
    print "Creating $dir \n";
    $dir->assert->open;
    $dir->close;
}

sub chdir_src {
    my $self = shift;
    my $dir = $self->src_dir;
    $dir->chdir;
}

sub create_config_yaml_file {
    require Config;
    no warnings 'once';
    my $self = shift;
    io('config.yaml')->print(<<"...");
# Generated by ${\ ref($self) } on ${\ scalar(localtime)}.
#
# Please edit these values appropriately and then run `make`.

maker_class: ${\ $self->maker_class}
dist_name: ${\ $self->guess_dist_name}
dist_version: 0.00
perl_path: $Config::Config{perlpath}
target_base: ..
...
}

sub create_new_makefile {
    my $self = shift;
    
    $self->require_class('maker_class')->new->make_new_makefile;
}

#-------------------------------------------------------------------------------
sub check_new_dir_path {
    my $self = shift;
    my $dir = shift;
    $dir = $dir->catdir('src')
      unless $dir->filename eq 'src';
    warn("Can't make new module in non-empty directory '$dir'\n"), exit
      if $dir->exists and not $dir->empty;
    return $dir;
}

sub guess_dist_name {
    my $self = shift;
    for (reverse $self->src_dir->absolute->splitdir) {
        next if $_ eq 'src';
        return $_ if /^[A-Z]/;
        return '...';
    }
}

1;

=head1 NAME

Module::Make - The New Way To make Modules

=head1 SYNOPSIS

    > perl -MModule::Make=new - Foo-Bar

=head1 NOTE

THIS VERSION OF THE MODULE IS NOT READY FOR PUBLIC USE.

=head1 DESCRIPTION

Writing Perl modules, especially modules intended for CPAN, requires a
lot of work that just isn't fun. Instead of just writing Perl code, you
need to write and maintain a bunch of auxilary files as well:

    * Makefile.PL
    * Changes
    * README
    * META.yml
    * MANIFEST

In addition you need to write and maintain docs. And you need to
keep a version number up to date etc. Much of this is automated by
various tools but wounldn't it be nice if more of this stuff just
happened for free?

Wouldn't it be nice if your boring code could be written for you?
Wouldn't it be nice if your comments turned into your documentation?
Wouldn't it be nice if C<make dist> really did everything you needed to
do including uploading to CPAN?
Wouldn't it be nice to have full control, but rarely need to lift a
finger?

Module::Make takes your Perl modules to the next level. Literally.

Using Module::Make you create a <src/> directory in your module
distribution, put a config.yaml file in there, along with various pre-
source files. Module::Make figures out how to put everything together to
make your actual distributable code.

=head1 IDEAS/TODO

Generate new env with:

    perl -MModule::Make:maker

MM is a base class to write Foo::Make. Like Kwiki::Make.

Templates can be pulled in from open svn repos.

Some config info should be kept outside of the module src. Things that
point to local absolute paths for instance.

MM require GNU-make or BSD-make environments. You can still generate
code that ill work on windows but you wouldn't develop there.

=head1 AUTHOR

Ingy döt Net <ingy@cpan.org>

=head1 COPYRIGHT

Copyright (c) 2007. Ingy döt Net. All rights reserved.

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

See http://www.perl.com/perl/misc/Artistic.html
