#!/usr/bin/env python
from waf_extensions import declare_variants, run_all, sub_conf, \
    build_emcc_lib, export_str_from_filenames, \
    configure_emscripten
import re
import os.path

variants = ['release_emscripten', 'debug_native']
declare_variants(variants,
                 subdir='lua')


def options(opt):
    opt.load('compiler_c')


def configure_debug_native(conf):
    conf.load('compiler_c')
    conf.check_cc(lib='m', uselib_store='math', mandatory=True)
    conf.env.append_value('CFLAGS', '-std=gnu99')
    conf.load('ar')
    conf.env.append_value('CFLAGS', '-g')


def configure(conf):
    if not conf.env['root']:
        conf.env['root'] = os.path.join(conf.path.abspath(), os.pardir,
                                        os.pardir)
    with sub_conf(conf, 'lua/release_emscripten'):
        configure_emscripten(conf)
    with sub_conf(conf, 'lua/debug_native'):
        configure_debug_native(conf)
    # The default build for the controller is handled by the controller


def build(bld):
    if not bld.variant:
        print('Building all variants.')
        run_all('build')
        return
    # Build for the controller and lua itself.
    # Currently, lua is only built on its own using emscripten.
    if 'controller' not in bld.variant and 'lua' not in bld.variant:
        return

    # We want to glob all files in the src directory which don't contain main
    # functions.
    main_re = re.compile(r'^ *int +main *\(', re.MULTILINE)
    paths = (bld.path.ant_glob("src/**/*.c") +
             bld.path.ant_glob("tenshi-runtime/src/**/*.c"))
    files = []

    # Filter out files which contain a main function
    for path in paths:
        with open(path.abspath()) as f:
            contents = f.read()
            if not main_re.search(contents):
                files.append(path)

    # Always build the objects.
    bld.objects(
        source=files,
        target="lua_objects",
        includes="src tenshi-runtime"
    )

    # Tenshi Runtime components written in Lua
    # TODO(rqou): Byte-compile them on the host
    lua_c_objs = []
    for path in bld.path.ant_glob("tenshi-runtime/src/lua/**/*.lua"):
        base_name = os.path.basename(str(path))
        lua_c_objs = lua_c_objs + [base_name + '.c']
        bld(
            rule='${root}/tools/bin2c.py '
                 '${SRC} '
                 'vm/lua/${TGT[0]} '
                 'vm/lua/${TGT[1]} ',
            source=path,
            target=base_name + '.c ' + base_name + '.h'
        )

    bld.objects(
        source=lua_c_objs,
        target="lua_lua_objects",
        includes="src tenshi-runtime"
    )

    if 'native' in bld.variant:
        bld.program(
            target='lua',
            source='src/lua.c',
            use='lua_objects lua_lua_objects math'
        )

        bld.program(
            target='luac',
            source='src/luac.c',
            use='lua_objects lua_lua_objects math'
        )

    bld.program(
        target='tenshi-runtime-test',
        source='tenshi-runtime/src/test_program.c',
        use='lua_objects lua_lua_objects math',
        includes="src tenshi-runtime"
    )

    if 'emscripten' in bld.variant:
        tenshi_runtime_headers = bld.path.ant_glob("tenshi-runtime/inc/**/*.h")
        tenshi_runtime_headers = map(
            lambda x: os.path.join('..', 'tenshi-runtime', 'inc', str(x)),
            tenshi_runtime_headers)

        lua_headers = ['lua.h', 'lauxlib.h', 'threading.h']

        headers = []

        for filename in lua_headers + list(tenshi_runtime_headers):
            headers.append(os.path.join(bld.env['root'], 'vm', 'lua', 'src',
                                        filename))

        export_str = export_str_from_filenames(headers)

        build_emcc_lib(
            bld,
            export_str,
            target='lua',
            use='lua_objects lua_lua_objects'
        )
