import sys, os
from distutils import util, ccompiler
from distutils.command import build

import Util

class Build(build.build):

    command_name = "build"

    description = "build everything needed to install"

    user_options = [
        ('build-base=', 'b', "base directory for build library"),
        ('build-lib=', None, "build directory for all distributions"),
        ('build-scripts=', None, "build directory for scripts"),
        ('build-temp=', 't', "temporary build directory"),
        ('build-tests=', None, 'build directory for tests'),
        ('build-docs=', None, 'build directory for documents'),
        ('build-l10n=', None, 'build directory for binary message catalogs'),
        ('compiler=', 'c', "specify the compiler type"),
        ('ldflags=', 'l', "specify additional linker options"),
        ('debug', 'g', "compile with debugging information"),
        ('force', 'f', "forcibly build everything (ignore file timestamps)"),

        ('with-docs', None, 'enable documentation build'),
        ('without-docs', None, 'disable documentation build [default]'),
        ]

    boolean_options = ['debug', 'force', 'with-docs', 'without-docs']

    negative_opt = {'without-docs' : 'with-docs'}

    help_options = [
        ('help-compiler', None,
         "list available compilers", ccompiler.show_compilers),
        ]

    def initialize_options(self):
        self.build_base = 'build'
        self.build_lib = None
        self.build_temp = None
        self.build_scripts = None
        self.build_tests = None
        self.build_docs = None
        self.build_l10n = None
        self.compiler = None
        self.ldflags = None
        self.with_docs = 0
        self.debug = 0
        self.force = 0
        return

    def finalize_options(self):
        self.set_undefined_options('config',
                                   ('compiler', 'compiler'),
                                   ('debug', 'debug'))

        plat_build = os.path.join(self.build_base,
                                  '%s.' + Util.GetPlatformSpecifier())

        # platform specific (can contain extension modules)
        if self.build_lib is None:
            self.build_lib = plat_build % 'lib'

        # platform specific (compiler by-products)
        if self.build_temp is None:
            self.build_temp = plat_build % 'temp'

        # platform specific (can have real executables)
        if self.build_scripts is None:
            self.build_scripts = plat_build % 'scripts'

        # all platforms (no compiled objects)
        if self.build_tests is None:
            self.build_tests = os.path.join(self.build_base, 'tests')

        # all platforms (no compiled objects)
        if self.build_docs is None:
            self.build_docs = os.path.join(self.build_base, 'docs')

        # all platforms (no compiled objects)
        if self.build_l10n is None:
            self.build_l10n = os.path.join(self.build_base, 'locale')
        return

    def run(self):
        self.run_command('config')

        # Run all relevant sub-commands.
        for cmd_name in self.get_sub_commands():
            self.run_command(cmd_name)
        return

    def get_source_files(self):
        files = []
        for cmd_name in self.get_sub_commands():
            cmd = self.get_finalized_command(cmd_name)
            files.extend(cmd.get_source_files())
        return files

    # -- Predicates for sub-command list -------------------------------

    def has_pure_modules (self):
        return self.distribution.has_pure_modules()

    def has_c_libraries (self):
        return self.distribution.has_c_libraries()

    def has_ext_modules (self):
        return self.distribution.has_ext_modules()

    def has_idl(self):
        return self.distribution.has_idl()

    def has_scripts (self):
        return self.distribution.has_scripts()

    def has_tests(self):
        return self.distribution.has_tests()

    def has_docs(self):
        return self.with_docs and self.distribution.has_docs()

    def has_l10n(self):
        return self.distribution.has_l10n()

    # a list of commands this command might have to run to do its work.
    sub_commands = [
        ('build_py', has_pure_modules),
        ('build_clib', has_c_libraries),
        ('build_ext', has_ext_modules),
        ('build_idl', has_idl),
        ('build_scripts', has_scripts),
        ('build_tests', has_tests),
        ('build_docs', has_docs),
        ('build_l10n', has_l10n),
        ]
