use 5.008;

use strict;
use warnings;

use ExtUtils::MakeMaker;
use File::Temp qw(:POSIX);
use Config;

# CCFLAGS
my @ccflags;

push @ccflags, "-g3" if $ENV{JS_DEBUG};

# Make sure we know what platform we are compiling for
my @defines;

my $path_separator = ":";
if($^O eq "MSWin32") {
    push @defines,  "XP_WIN";
    $path_separator = ";";
} else {
    push @defines, "XP_UNIX";
}

# Name of lib to link
my $lib = "js";

# Directories with include files
my @incs;

# Directories with libraries
my @libs;

# Extra header files (sans .h)
my @extra_headers;

# Directory to prefix #include with
my $inc_dir = "";

#test for debian type libsmjs
#this could probably be done better, but I'm not sure how to
#get this platform independant
if (-f "/usr/lib/libmozjs.so" or -f "/usr/local/lib/libmozjs.so") {
    $lib = "mozjs";
}
elsif (-f "/usr/lib/libsmjs.so" or -f "/usr/local/lib/libsmjs.so") {
    $lib = "smjs";
}
if (-f "/usr/include/smjs/jsapi.h") {
    push @incs, "/usr/include/smjs/";
    push @defines, "INCLUDES_IN_SMJS";
    $inc_dir = "smjs/";
}
elsif(-f "/usr/local/include/smjs/jsapi.h") {
    push @incs, "/usr/local/include/smjs/";
    push @defines, "INCLUDES_IN_SMJS";
}
elsif(-f "/usr/include/mozjs/jsapi.h") {
    push @incs, "/usr/include/mozjs/";
    push @defines, "INCLUDES_IN_MOZJS";
    $inc_dir = "mozjs/";
}
elsif(-f "/usr/local/include/mozjs/jsapi.h") {
    push @incs, "/usr/local/include/mozjs/";
    push @defines, "INCLUDES_IN_MOZJS";
}

# Debian puts nspr headers in /usr/include/nspr
if (-f "/usr/include/nspr/pratom.h") {
    push @incs, "/usr/include/nspr/";
}
# RHEL5/CentOS5 use /usr/include/nspr4 for nspr headers
elsif (-f "/usr/include/nspr4/pratom.h") {
    push @incs, "/usr/include/nspr4/";
}

# test for gentoo
if(-f "/etc/gentoo-release") {
    # Gentoo puts libjs in a slightly hidden spot.
    @incs = qw(/usr/lib/MozillaFirefox/include/js/
              /usr/lib/MozillaFirefox/);

}

# test for MacPorts
if (-d "/opt/local/include/js") {
    push @incs, "/opt/local/include/js", "/opt/local/include/nspr";
    push @libs, "/opt/local/lib";
}

# Override with $ENV{JS_LIB} and $ENV{JS_INC}
if (exists $ENV{JS_LIB}) {
    @libs = get_paths($ENV{JS_LIB});
    $ENV{DYLD_LIBRARY_PATH} = $ENV{LD_LIBRARY_PATH} = $ENV{JS_LIB};
    $lib = "js";
}
if (exists $ENV{JS_INC}) {
    @incs = get_paths($ENV{JS_INC});
    @defines = grep { $_ ne "INCLUDES_IN_SMJS" } @defines;
    $inc_dir = "";
}

my $libs = join(" ", map { "-L$_" } @libs);

# Handle threadsafe
if(exists $ENV{JS_THREADSAFE}) {
    push @defines, "JS_THREADSAFE" if $ENV{JS_THREADSAFE};
}
else {
    my $enable_threadsafe = prompt("Is your SpiderMonkey compiled with JS_THREADSAFE (most things will fail if you answer wrong)? [y/N]");
    push @defines, "JS_THREADSAFE" if $enable_threadsafe eq "y";
}

if (grep /^JS_THREADSAFE$/, @defines) {
   print "Whoa there! Attention! You have asked me to build a JavaScript.pm that links against a SpiderMonkey built with ";
   print "JS_THREADSAFE defined. Although must things will proabaly work as expected some might not and I really ";
   print "don't put much effort into supporting JS_THREADSAFE (actually none expect accept some patches). ";
   print "If you are using a JS_THREADSAFE it's likely because your OS vendor supplied the SpiderMonkey libs you're using ";
   print "and instead I recommend you to download and build your own SpiderMonkey libs that doesn't use JS_THREADSAFE.\n";
}

# Check if we need to enable JS_C_STRINGS_ARE_UTF8?
if(exists $ENV{JS_UTF8}) {
    push @defines, "JS_C_STRINGS_ARE_UTF8" if $ENV{JS_UTF8};
}
else {
    my $enable_utf8 = prompt("Is your SpiderMonkey compiled with support for unicode (t/23-unicode.t will fail if you answer wrong) ? [y/N]", "N");
    push @defines, "JS_C_STRINGS_ARE_UTF8" if $enable_utf8 eq "y";
}

# Check if we want E4X support
if (exists $ENV{JS_ENABLE_E4X}) {
    if ($ENV{JS_ENABLE_E4X}) {
        push @extra_headers, "jsxml";
        push @defines, "JS_ENABLE_E4X";
    }
}
else {
    my $enable_e4x = prompt("Do you want support for E4X (requires SpiderMonkey > 1.5) ? [y/N]", "N");
    if ($enable_e4x eq "y") {
        push @extra_headers, "jsxml";
        push @defines, "JS_ENABLE_E4X";     
    }
}

if ($ENV{JS_LIB_NAME}) { $lib = $ENV{JS_LIB_NAME} }

# Write JavaScript_Env.h
open my $header, ">JavaScript_Env.h" || die $!;

print $header "/* This file is autogenerated to suite your platform */\n\n";

print $header "#ifndef __JAVASCRIPT_ENV_H__\n#define __JAVASCRIPT_ENV_H__\n\n";

print $header join("\n", map { "#define $_"} @defines), "\n\n";

foreach my $inc_file (qw(jsapi jsdbgapi jsinterp jsfun jsobj jsprf jsscope), @extra_headers) {
    print $header "#include <${inc_dir}${inc_file}.h>\n";
}

print $header "\n#endif\n";

close $header;

unless ($ENV{JS_FORCE}) {
    # Try a small compile to determine if we can find libs and headers
    open(my $test_script, ">", "test_js.c") || die $!;
    print $test_script <<'END_OF_SOURCE';
#include <stdio.h>
#include "JavaScript_Env.h"

int main(int argc, char **argv) {
    printf("%s", JS_GetImplementationVersion());
}
END_OF_SOURCE
    close $test_script;

    my $exe = tmpnam();;
    my $cc = join(" ", $Config{cc}, @ccflags, "-o", $exe, "test_js.c", "-I.", (map { "-I$_" } @incs), $libs, "-l${lib}" );
    qx($cc);
    if ($?) {
        print "Failed compiling test_js.c. ABORTING\n\n$cc\n";
        exit 0;
    }
    unlink("test_js.c");

    # Get js version and require 1.7 or later
    my ($engine, $version, $date) = split/\s+/, qx($exe);
    my ($v2) = $version =~ /^(\d+\.\d+)/;
    if ($v2 < 1.7) {
        if (prompt("I require SpiderMonkey version 1.7 or later but found ${version}. Try anyways? [y/N]", "N") ne "y") {
            exit 0;
        }
    }

    # Dispose temp stuff
    unlink($exe);
}
else {
    print "Skipping build test since JS_FORCE is set\n";
}

# Write makefile
my $libs_flags = "";
if($^O eq "MSWin32") {
    $libs_flags = ":nosearch";
}

WriteMakefile(
    NAME            => "JavaScript",
    VERSION_FROM    => "lib/JavaScript.pm",
    PREREQ_PM       => {
        "Test::More"      => 0,
        "Test::Exception" => 0,
    },
    ABSTRACT_FROM   => "lib/JavaScript.pm", # retrieve abstract from module
    AUTHOR          => "Claes Jakobsson <claesjac\@cpan.org>",
    CCFLAGS         => join(" ", @ccflags),
    LIBS            => ["$libs_flags $libs -l${lib}"], # e.g., "-lm"
    INC             => join(" ", map { "-I$_" } @incs),
    LICENSE         => "perl",
    OBJECT          => q/$(O_FILES)/,
    META_MERGE      => {
        resources => {
            repository => "svn://svn.versed.se/public/Perl/modules/JavaScript"
        }
    },
);

sub get_paths {
    my $paths = shift;
    my @paths = map { s/^\s+//; s/\s+$//; $_ } split/$path_separator/, $paths;
    return @paths;
}

package MY;

use File::Spec;

sub post_initialize {
    my($self) = shift;

    my @headers = <*.h>;
    for (@headers, 'typemap' ) {
        $self->{PM}->{$_} = File::Spec->catfile($self->{INST_ARCHAUTODIR}, $_);
    }
    return '';
}