import os

from waflib import Utils, Build
from waflib.TaskGen import feature, before_method, after_method
from waflib.Task import compile_fun


def options(opt):
    opt.load("compiler_c")
    opt.add_option("--enable-test", action="store_true", default=False,
                   dest="test", help="build tests")
    opt.add_option("--disable-test", action="store_false",
                   dest="test", help="do not build tests (default)")


def configure(conf):
    conf.msg_feature("Tests", conf.options.test)
    if not conf.options.test:
        return

    conf.env.BUILD_TEST = True
    conf.load("compiler_c")
    conf.find_program("cmake", var="CMAKE")
    conf.find_program("make", var="MAKE")

    if conf.env.STATIC and conf.env.DEST_OS_NORMALIZED == "windows":
        lib_param_name = "stlib"
    else:
        lib_param_name = "lib"

    if not any(conf.check_cxx(
                   uselib_store="PTHREAD",
                   mandatory=False,
                   **{lib_param_name: x}
               )
               for x in ["pthreads", "pthread"]):
        conf.fatal("Can't find pthread.")

    googletest_dir = Utils.subst_vars("${VENDORLIBS}/googletest", conf.env)
    if not os.path.isfile(os.path.join(googletest_dir, "CMakeLists.txt")):
        conf.fatal("Can't find Google Test, please run 'git submodule update --init --recursive' to update git submodules")

    conf.env.GTEST_ROOT = googletest_dir


@feature('static')
@after_method('apply_link')
def make_fully_static(self):
    assert self.link_task
    self.link_task.hcode += " -Wl,-Bstatic"
    func, _ = compile_fun(self.link_task.hcode)
    self.link_task.run = lambda: func(self.link_task)

@feature('static')
@before_method('apply_link')
def make_fully_static_before(self):
    self.env.append_unique("LINKFLAGS", ["-static"])


def build(bld):
    if not bld.env.BUILD_TEST:
        return

    bld.post_mode = Build.POST_BOTH

    bld.add_group()
    gtest_build = bld.path.get_bld().make_node("gtest")
    gtest_build.mkdir()

    makefile = gtest_build.make_node("Makefile")
    cmakelists = bld.root.find_node(bld.env.GTEST_ROOT + "/CMakeLists.txt")
    bld(
        rule="CXX=${CXX} CC=${CC} ${CMAKE} ${GTEST_ROOT}",
        source=cmakelists,
        target=makefile,
        cwd=gtest_build.abspath(),
    )
    gtest_output = [gtest_build.make_node(x)
                    for x in ("libgtest.a", "libgtest_main.a")]
    bld(
        name="gtest",
        rule="${MAKE}",
        source=makefile,
        target=gtest_output,
        cwd=gtest_build.abspath(),
    )
    bld(
        rule="${PYTHON3} ${SRC[0].abspath()} > ${TGT[0].abspath()}",
        source="build_core_param_set.py",
        target=bld.path.find_node("test_core_param_set.h"),
        cwd=bld.path.abspath(),
    )
    bld.add_group()
    test_output = bld.path.get_bld().make_node("f3kdb-test")
    bld(
        features="cxx cxxprogram %s" % ((
            "static" if
            bld.env.STATIC and bld.env.DEST_OS_NORMALIZED == "windows"
            else ""
        ),),
        source=bld.path.ant_glob(
            ["*.cpp"],
            excl=[
                "stdafx.cpp",
            ],
        ),
        includes=[Utils.subst_vars("${GTEST_ROOT}/include", bld.env)],
        use=["f3kdb", "gtest"],
        uselib=["PTHREAD"],
        stlib=["gtest", "gtest_main"],
        stlibpath=[gtest_build.abspath()],
        linkflags="-Wl,-rpath={}:.:..".format(
            bld.path.get_bld().parent.abspath()
        ),
        target=test_output,
    )
    [bld.add_manual_dependency(test_output, x) for x in gtest_output]
