# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
top = '..'

from waflib import Options, Errors

def options(opt):
    for subdir in opt.path.ant_glob(['*'], dir=True, src=False):
        opt.add_option('--enable-%s' % subdir,
                   help='Build tool %s, enabled by default' % subdir,
                   action='store_true',
                   dest='enable_%s' % subdir)

        opt.add_option('--disable-%s' % subdir,
                   help='Do not build tool %s' % subdir,
                   action='store_true',
                   dest='disable_%s' % subdir)

        opt.recurse(str(subdir), mandatory=False)


def configure(conf):
    all_tools = set() # all available tools
    enabled_tools = set() # --enable-X
    disabled_tools = set() # --disable-X

    Options.options.disable_pib = True

    for subdir in conf.path.ant_glob(['*'], dir=True, src=False):
        tool = str(subdir)
        all_tools.add(tool)

        is_enabled = getattr(Options.options, 'enable_%s' % tool)
        is_disabled = getattr(Options.options, 'disable_%s' % tool)

        if is_enabled and is_disabled:
            raise Errors.WafError("--enable-%s and --disable-%s cannot be both specified" % (tool, tool))

        if is_enabled:
            enabled_tools.add(tool)

        if is_disabled:
            disabled_tools.add(tool)

    if len(enabled_tools) == 0:
        conf.env['BUILD_TOOLS'] = list(all_tools - disabled_tools)
    else:
        conf.env['BUILD_TOOLS'] = list(enabled_tools)

    for tool in conf.env['BUILD_TOOLS']:
        conf.recurse(tool, mandatory=False)

    conf.msg("Tools to build", ", ".join(conf.env['BUILD_TOOLS']))

def build(bld):
    for tool in bld.env['BUILD_TOOLS']:
        bld.recurse(tool)
