
=pod

=head1 NAME

SDLpp - Package your SDL games

=head1 SETUP

 cpan Alien::SDL SDL

 cpan Module::ScanDeps 

version 0.97 needed

 cpan PAR::Packer 

version 1.004 needed

pip http://strawberryperl.com/package/kmx/perl-modules-patched/PAR-1.000_patched.tar.gz

=head1 USAGE

  perl SDLpp.pl --output=a.exe  --input=script.pl --nclude=./lib --more=Foo::Bar,Bar::Foo 

=head1 AUTHOR

kthakore 

=cut

use strict;
use warnings;
use SDL;
use Alien::SDL;
use Getopt::Long;
use File::Spec;
use File::Find qw/finddepth/;

use Data::Dumper;
use Archive::Zip qw( :ERROR_CODES :CONSTANTS );

#Checking if we have the pp installed
die 'Need PAR::Packer' if !( eval ' use PAR::Packer; 1' );

#Default out put is a or a.exe for windows
my $output = 'a';
$output .= '.exe' if $^O =~ /win32/ig;

my $libs = 'SDL,SDL-1.2,SDLmain';

my $input;

my $Include = '';

my $extra = '';

my $result = GetOptions(
	"output=s" => \$output,
	"libs=s"   => \$libs,
	"input=s"  => \$input,
	"nclude=s" => \$Include,
	"more=s"   => \$extra,
	"help"     => sub { usage() },
);

$extra = '-M ' . $extra if $extra;
$extra =~ s/,/ \-M /g;

my @sdl_libs = split ',', $libs;

sub usage {
	print
		" perl SDLpp.pl --output=a.exe --libs=SDL,SDL_main,SDL_gfx  --input=script.pl --nclude=./lib --more=Foo::Bar,Bar::Foo \n"
		. " if --libs is not define only SDL,SDL-1.2,SDLmain libs are packaged \n";

	exit;
}

if ( !$input ) {
	warn 'Input needs to be specified.';
	usage;
}

print "BUILDING PAR \n";
my $exclude_modules = '-X Alien::SDL::ConfigData -X SDL::ConfigData';
my $include_modules = '-M ExtUtils::CBuilder::Base -M Data::Dumper -M SDL -M Alien::SDL';
$include_modules .= " $extra" if $extra;

my $out_par = $output . '.par';
my $par_cmd = "pp -B $exclude_modules $include_modules";
$par_cmd .= " -I $Include" if $Include;
$par_cmd .= " -p -o $out_par $input";

print "\t $par_cmd \n";

`$par_cmd` if !-e $out_par;

print "PAR: $out_par\n" if -e $out_par;

print "SEARCHING FOR ConfigData files \n";
my $lib;
my $AS_path;
my $SD_path;

finddepth( \&wanted, @INC );

sub wanted {

	if ( $_ =~ /ConfigData/ ) {
		$AS_path = $File::Find::name
			if $File::Find::name =~ 'Alien/SDL/ConfigData.pm';
		$SD_path = $File::Find::name
			if $File::Find::name =~ 'SDL/ConfigData.pm'
				&& $File::Find::name !~ 'Alien/SDL/ConfigData.pm';

		$lib = $File::Find::dir if ( $AS_path && $SD_path );
	}
}

die "Cannot find lib/SDL/ConfigData.pm or lib/Alien/SDL/ConfigData.pm \n"
	if ( !$AS_path || !$SD_path );

print "Found ConfigData files in $lib \n";

print "READING PAR FILE \n";

my $par_file = Archive::Zip->new();
unless ( $par_file->read($out_par) == AZ_OK ) {
	die 'read error on ' . $out_par;
}

$par_file->addFile( $AS_path, 'lib/Alien/SDL/ConfigData.pm' );
$par_file->addFile( $SD_path, 'lib/SDL/ConfigData.pm' );

my $share = Alien::SDL::ConfigData->config('share_subdir');

my @shares = $par_file->membersMatching($share);

my $alien_sdl_auto = $shares[0]->fileName;

$alien_sdl_auto =~ s/$share(\S+)// if $alien_sdl_auto;

my @auto_folder = $par_file->membersMatching("$alien_sdl_auto(?!$share)");

my @sdl_not_runtime = $par_file->membersMatching( $share . '/include' ); #TODO remove extra fluff in share_dri
push @sdl_not_runtime, @auto_folder;                                     #remove non share dir stuff
push @sdl_not_runtime, $par_file->membersMatching( $share . '/etc' );
push @sdl_not_runtime, $par_file->membersMatching( $share . '/share' );
push @sdl_not_runtime, $par_file->membersMatching( $share . '/lib' )
	if $^O =~ /win32/ig;

my @non              = ();
my @sdl_libs_to_keep = ();

foreach (@sdl_libs) {
	if ( $^O =~ /win32/ig ) {
		@non = $par_file->membersMatching( $share . "/bin(\\S+)" );

		#push @sdl_not_runtime ,$par_file->membersMatching( $share."/bin(\\S+)(?!$_)" )
	} else {
		@non = $par_file->membersMatching( $share . "/lib(\\S+)" );
	}

	print "Removing non $_ shared objs \n";
	my $lib_look = 'lib' . $_;
	map {
		my $n = $_->fileName;
		if ( $n =~ /$lib_look\.(so|a|dll|dylib)/ ) {
			push( @sdl_libs_to_keep, $_ );
		}

	} @non;

}

print "found $#sdl_libs_to_keep sdl libs to keep \n";
my $regex_search = ']';
map {
	print "\t " . $_->fileName . "\n";
	$regex_search .= ']' . $_->fileName
} @sdl_libs_to_keep;

$regex_search =~ s/\]\]//g;
$regex_search =~ s/\]/\|/g;

$regex_search = '(' . $regex_search . ')';

map {
	my $n    = $_->fileName;
	my $star = ' ';

	if ( $n !~ $regex_search ) {
		push @sdl_not_runtime, $_;
	}
} @non;

push @sdl_not_runtime, $par_file->membersMatching( $share . '/bin' )
	unless $^O =~ /win32/ig;
print "REMOVING NON RUNTIME $#sdl_not_runtime files from  \n";
open( my $FH, '>', 'DeleteRecords.txt' ) or die $!;
foreach (@sdl_not_runtime) {
	if ( $_->fileName eq $alien_sdl_auto . $share ) {
		print $FH "Not deleting " . $_->fileName . " \n";
	} else {
		$par_file->removeMember($_);
		print $FH $_->fileName . "\n";
	}

}
close $FH;

my @config_members = $par_file->membersMatching('ConfigData.pm');

foreach (@config_members) {
	$_->desiredCompressionLevel(1);
	$_->unixFileAttributes(0644);
}

unlink $out_par . '2';
unless ( $par_file->writeToFileNamed( $out_par . '2' ) == AZ_OK ) {
	die 'write error';
}

$par_cmd = "pp -o $output " . $out_par . "2";

`$par_cmd`;

print "MADE $output \n" if -e $output;
unlink $out_par . '2';
unlink $out_par;
