#! /usr/local/bin/perl

use strict;
use warnings; 
no warnings 'redefine';
use Data::Dumper;
use FileHandle;
use ExtUtils::MakeMaker;
use Module::Build;

my %convert;
our $INTEND;

my $DEBUG = 0;
my $MAKEFILE = 'Makefile.PL';
my $BUILD_PL = 'Build.PL';
my $LEN_INTEND = 4;

*ExtUtils::MakeMaker::WriteMakefile = \&_convert;

_run_makefile();

sub _run_makefile {
    -e $MAKEFILE
      ? do $MAKEFILE
      : die "No $MAKEFILE found\n";
}

sub _convert {
    _get_conversion_table();
    
    print "Converting $MAKEFILE -> $BUILD_PL\n";
    
    _output(_dump(&_args_build));
}

sub _get_conversion_table {
    local $/ = '';
    local $_ = <DATA>;
    %convert = split;
}

sub _args_build { 
    my %args_make = @_;
    my @args_build;
    
    for my $arg (keys %args_make) {
        next unless $convert{$arg};
	
	# HASH CONVERSION
        if (ref $args_make{$arg} eq 'HASH') { 
	    _debug("$convert{$arg} => \{ ");
	    
	    my(%subargs, $subargs_count);
	    
	    my $subargs_size = %{$args_make{$arg}};
	    $subargs_size = chop($subargs_size);
	    
	    for my $subarg (keys %{$args_make{$arg}}) {
	        _debug("$subarg => $args_make{$arg}{$subarg}");
	        _debug(', ') if (++$subargs_count < $subargs_size);
		 
	        $subargs{$subarg} = $args_make{$arg}{$subarg};
	    }
	    _debug(" },\n");
	    
            my %tmphash;
	    %{$tmphash{$convert{$arg}}} = %subargs;
	    push @args_build, \%tmphash;
	}
	# ARRAY CONVERSION
	elsif (ref $args_make{$arg} eq 'ARRAY') {
	    warn "Warning: $arg - array conversion not supported\n";
	}
	# SCALAR CONVERSION
	#
	# One-dimensional hash values (scalars),
	# don't justify as SCALARS.
        elsif (ref $args_make{$arg} eq '') { 
	    _debug("$convert{$arg} => \'$args_make{$arg}\',\n");
	    
	    my %tmphash;
	    $tmphash{$convert{$arg}} = $args_make{$arg};
	    push @args_build, \%tmphash;
	}
	else { 
	    warn "Warning: $arg - unknown type of argument";
	}
    }    
    
    return \@args_build;
}

sub _dump {
    my($args) = @_;

    $Data::Dumper::Indent    = 2;
    $Data::Dumper::Quotekeys = 0;
    $Data::Dumper::Sortkeys  = 1;
    $Data::Dumper::Terse     = 1;
    
    my $d = Data::Dumper->new([ @$args ]);
    
    return [ $d->Dump ];
}

sub _output { 
    local $INTEND = ' ' x $LEN_INTEND;
    
    local *F_BUILD; 

    _open_build_pl();

    _output_header();
    &_output_args;
    _output_footer();
    
    _close_build_pl();
}

sub _open_build_pl {
    open F_BUILD, ">$BUILD_PL" or 
      die "Couldn't open $BUILD_PL: $!";
      
    select F_BUILD;
}

sub _close_build_pl {
    close F_BUILD or
      die "Couldn't close $BUILD_PL: $!";
      
    select STDOUT; 
}

sub _output_header {
    local $INTEND = $INTEND;
    chop($INTEND);
    
    print <<"EOT";
    
use Module::Build;

my \$b = Module::Build->new
$INTEND(
EOT
}

sub _output_args {
    my($args) = @_;
    
    for my $arg (@$args) {
        if ($arg =~ m#=> \{#s) {
	    $arg =~ s#\{ .*?\n (.*? \}) \s+ \}#$1#osx;
	    
	    my @arg = @{_split_arg($arg)};
	    
	    my($whitespace) = $arg[0] =~ m#(\s+)\w+#o;
	    my $shorten = length($whitespace);

            for my $arg (@arg) {
	        chomp($arg);
	        $arg =~ s/\s{$shorten}(.*)/$1/o;
	        $arg .= ',' if ($arg =~ m#\d$# || $arg =~ m#\}#);
	        print "$INTEND$arg\n";
            }
	}
	else {
            $arg =~ s#\{ \s+ (.*) \s+ \}#$1#ox;
	    chomp($arg);
	    print "$INTEND$arg,\n";
	}
    }
}

sub _output_footer {
    local $INTEND = $INTEND;
    chop($INTEND);
    
    print <<"EOT";
$INTEND create_makefile_pl => 'traditional',
  );

\$b->create_build_script;
EOT
}

sub _split_arg {
    my($arg) = @_;
    
    my @arg;        
    while ($arg =~ s#(.*?\n) (.*)#$2#osx) {
        push @arg, $1;
    }
    
    return \@arg;
}

sub _debug {
    print @_ if $DEBUG;
}

__DATA__

NAME         module_name
PREREQ_PM    requires

1;
