# vim: set filetype: py

Import("dev source_path setLuaEnv")

targets = []
build_path = dev.get_build_path(source_path)

import os.path


def runCommand(cmd):
    import subprocess

    try:
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
        (output, err) = p.communicate()
        return output
    except Exception as e:
        print(e)
        return ""


def getRbConf(name):
    return runCommand(
        [dev.env["ruby"], "-rmkmf", "-e", "print RbConfig.expand('$(" + name + ")')"]
    )


def buildRbModule():
    env = dev.env.Clone()
    conf = Configure(
        env,
        conf_dir=dev.get_build_path(".sconf_temp"),
        log_file=dev.get_build_path("config.log"),
        clean=False,
        help=False,
    )

    if not runCommand([dev.env["ruby"], "-v"]):
        print("Ruby not found, skipping ruby module")
        return

    env.Append(SWIGFLAGS=["-c++", "-Wall", "-ruby", "-autorename"])

    import distutils.sysconfig

    libdir = getRbConf("libdir")
    if not libdir:
        print("Ruby libdir not found, skipping ruby module")
        return

    incdir = getRbConf("rubyhdrdir")
    if not incdir:
        print("Ruby hdrdir not found, skipping ruby module")
        return

    arch = getRbConf("arch")
    if not arch:
        print("Ruby arch not found, skipping ruby module")
        return

    soname = getRbConf("RUBY_SO_NAME")
    if not soname:
        print("Ruby RUBY_SO_NAME not found, skipping ruby module")
        return

    env.Append(LIBPATH=[libdir])
    env.Append(CPPPATH=["#", incdir, os.path.join(incdir, arch)])
    env.Append(LIBS=[soname, "adchpp"])

    if not conf.CheckCHeader("ruby.h"):
        print("ruby.h not found, skipping ruby module")
        conf.Finish()
        return
    conf.Finish()

    ruby_wrap = dev.get_build_path(source_path) + "ruby_wrap.cxx"

    f = env.CFile(target=ruby_wrap, source="ruby.i")

    doc_path = env.Dir(dev.get_target(source_path, "doc/")).path
    env["DOCPATH"] = doc_path
    # TODO make it not rebuild every time...
    # docs = env.Command(doc_path + "/index.html", ruby_wrap, "rdoc -o \"$DOCPATH\" $SOURCES")

    if "_DEBUG" in env["CPPDEFINES"]:
        env["CPPDEFINES"].remove("_DEBUG")

    rb = env.SharedLibrary(dev.get_target(source_path, "rbadchpp"), [f], SHLIBPREFIX="")

    targets.append(rb)


def buildPyModule():

    print("swig/SConscript > buildPyModule needs updates -> disabled for now.")
    return

    import sys

    env, target, sources = dev.prepare_build(source_path, "_pyadchpp", "python.i")
    env.Append(
        SWIGFLAGS=[
            "-c++",
            "-threads",
            "-Wall",
            "-python",
            "-O",
            "-modern",
            "-features",
            "autodoc=1",
        ]
    )
    env["SWIGOUTDIR"] = Dir(dev.get_build_path("bin"))

    version = sys.version[0] + sys.version[2]

    if version not in ("25", "26", "27"):
        print("Invalid Python version: " + version + " - skipping Python module")
        return

    env.Append(CPPPATH=["#"])
    if "_DEBUG" in env["CPPDEFINES"]:
        env["CPPDEFINES"].remove("_DEBUG")
    if "/MDd" in env["CCFLAGS"]:
        env["CCFLAGS"].remove("/MDd")
        env["CCFLAGS"].append("/MD")

    if dev.is_win32():
        pyprefix = env["python"]
        incpath = os.path.join(pyprefix, "include")
        libpath = os.path.join(pyprefix, "libs")

        env.Append(LIBPATH=[libpath])
        env.Append(LIBS=["python" + version])
        env.Append(CPPPATH=[incpath])

    else:
        import distutils

        env.Append(CPPPATH=[distutils.sysconfig.get_python_inc()])
        env.Append(LIBS=["python" + sys.version[0:3]])

    env.Append(LIBS=["adchpp"])

    found = False
    for p in env["CPPPATH"]:
        if os.path.exists(os.path.join(p, "Python.h")):
            found = True
            break

    if not found:
        print("Python.h not found, not building python extension")
        return

    if dev.is_win32():
        env["SHLIBSUFFIX"] = ".pyd"

    pyd = env.SharedLibrary(target, sources, SHLIBPREFIX="")
    targets.append(pyd)


def buildLuaModule(lib, mod, plugin):
    env, target, sources = dev.prepare_build(source_path, lib, mod)

    env["SWIGOUTDIR"] = Dir(dev.get_build_path("bin"))

    env.Append(SWIGFLAGS=["-c++", "-Wall", "-lua"])

    env.Append(LIBS=["adchpp"])
    if (dev.is_win32() or env["PLATFORM"] == "cygwin") and "Bloom" in dev.env[
        "plugins"
    ]:
        env.Append(LIBS=["Bloom"])

    env.Append(CPPPATH=["#"])

    # We assume the lua from the script plugin will be used...
    setLuaEnv(env)

    if dev.is_win32():
        env.Append(CPPDEFINES=["LUA_BUILD_AS_DLL=1"])
    else:
        env.Append(CPPDEFINES=["LUA_USE_LINUX=1"])

    # on x64, SWIG includes some unsafe pointer conversions that the compiler of course disallows...
    if "gcc" in env["TOOLS"] and env["arch"] == "x64":
        env.Append(CPPFLAGS=["-fpermissive"])

    if plugin:
        env.Replace(UNDEF="")

    luadchpp = env.SharedLibrary(target, sources, SHLIBPREFIX="")
    targets.append(luadchpp)


def buildPHPModule():
    env, target, sources = dev.prepare_build(source_path, "php_adchpp", "php.i")

    if not dev.is_win32():
        print("No Linux support for PHP extensions yet")
        # TODO add Linux support (see TODO below)
        return

    php_path = "#/php/"
    if env["arch"] != "x86":
        php_path = php_path + env["arch"] + "/"

    if dev.is_win32():
        if env["CC"] == "cl":  # MSVC
            if not os.path.exists(env.File(php_path + "lib/php5.lib").abspath):
                print("No php5.lib file, skipping PHP")
                return
        else:
            print("Skipping the PHP module, use MSVC or Linux")
            return

    bin_dir = dev.get_build_path("bin")

    env["SWIGOUTDIR"] = Dir(bin_dir)
    env.Append(SWIGFLAGS=["-c++", "-Wall", "-php"])

    env.Append(CPPPATH=["#", bin_dir])
    env.Append(LIBS=["adchpp"])

    if dev.is_win32():
        env.Append(
            CPPPATH=[
                php_path + "include/",
                php_path + "include/main/",
                php_path + "include/TSRM/",
                php_path + "include/Zend/",
            ]
        )
        env.Append(
            CPPDEFINES=[
                "WIN32",
                "PHP_WIN32=1",
                "ZEND_WIN32=1",
                "PHP_DEBUG=0",
                "ZEND_DEBUG=0",
                "_USE_32BIT_TIME_T=1",
            ]
        )
        env.Append(LIBPATH=[php_path + "lib/"])
        env.Append(LIBS=["php5"])

    else:
        pass  # TODO run "php-config --includes"

    php_adchpp = env.SharedLibrary(target, sources, SHLIBPREFIX="")
    targets.append(php_adchpp)


if "ruby" in dev.env["langs"]:
    buildRbModule()

if "python" in dev.env["langs"]:
    if dev.env["PLATFORM"] == "win32" and dev.env["arch"] != "x86":
        print(
            "Skipping Python module because build platform is Windows and ARCH != x86"
        )
    else:
        buildPyModule()

if "lua" in dev.env["langs"]:
    buildLuaModule("luadchpp", "lua.i", False)
    if "Bloom" in dev.env["plugins"]:
        buildLuaModule("luadchppbloom", "bloom.i", True)

# TODO buildPHPModule()

Return("targets")
