"""custom

Custom builders and methods.

"""

#
# Copyright 2008 VMware, Inc.
# All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sub license, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice (including the
# next paragraph) shall be included in all copies or substantial portions
# of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#


import os.path
import sys
import subprocess
import modulefinder

import SCons.Action
import SCons.Builder
import SCons.Scanner

import fixes

import source_list

# the get_implicit_deps() method changed between 2.4 and 2.5: now it expects
# a callable that takes a scanner as argument and returns a path, rather than
# a path directly. We want to support both, so we need to detect the SCons version,
# for which no API is provided by SCons 8-P

# Scons version string has consistently been in this format:
# MajorVersion.MinorVersion.Patch[.alpha/beta.yyyymmdd]
# so this formula should cover all versions regardless of type
# stable, alpha or beta.
# For simplicity alpha and beta flags are removed.
scons_version = tuple(map(int, SCons.__version__.split('.')[:3]))

def quietCommandLines(env):
    # Quiet command lines
    # See also http://www.scons.org/wiki/HidingCommandLinesInOutput
    env['ASCOMSTR'] = "  Assembling $SOURCE ..."
    env['ASPPCOMSTR'] = "  Assembling $SOURCE ..."
    env['CCCOMSTR'] = "  Compiling $SOURCE ..."
    env['SHCCCOMSTR'] = "  Compiling $SOURCE ..."
    env['CXXCOMSTR'] = "  Compiling $SOURCE ..."
    env['SHCXXCOMSTR'] = "  Compiling $SOURCE ..."
    env['ARCOMSTR'] = "  Archiving $TARGET ..."
    env['RANLIBCOMSTR'] = "  Indexing $TARGET ..."
    env['LINKCOMSTR'] = "  Linking $TARGET ..."
    env['SHLINKCOMSTR'] = "  Linking $TARGET ..."
    env['LDMODULECOMSTR'] = "  Linking $TARGET ..."
    env['SWIGCOMSTR'] = "  Generating $TARGET ..."
    env['LEXCOMSTR'] = "  Generating $TARGET ..."
    env['YACCCOMSTR'] = "  Generating $TARGET ..."
    env['CODEGENCOMSTR'] = "  Generating $TARGET ..."
    env['INSTALLSTR'] = "  Installing $TARGET ..."


def createConvenienceLibBuilder(env):
    """This is a utility function that creates the ConvenienceLibrary
    Builder in an Environment if it is not there already.

    If it is already there, we return the existing one.

    Based on the stock StaticLibrary and SharedLibrary builders.
    """

    try:
        convenience_lib = env['BUILDERS']['ConvenienceLibrary']
    except KeyError:
        action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
        if env.Detect('ranlib'):
            ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
            action_list.append(ranlib_action)

        convenience_lib = SCons.Builder.Builder(action = action_list,
                                  emitter = '$LIBEMITTER',
                                  prefix = '$LIBPREFIX',
                                  suffix = '$LIBSUFFIX',
                                  src_suffix = '$SHOBJSUFFIX',
                                  src_builder = 'SharedObject')
        env['BUILDERS']['ConvenienceLibrary'] = convenience_lib

    return convenience_lib


def python_scan(node, env, path):
    # http://www.scons.org/doc/0.98.5/HTML/scons-user/c2781.html#AEN2789
    # https://docs.python.org/2/library/modulefinder.html
    contents = node.get_contents()

    # Tell ModuleFinder to search dependencies in the script dir, and the glapi
    # dirs
    source_dir = node.get_dir().abspath
    GLAPI = env.Dir('#src/mapi/glapi/gen').abspath
    path = [source_dir, GLAPI] + sys.path

    finder = modulefinder.ModuleFinder(path=path)
    finder.run_script(node.abspath)
    results = []
    for name, mod in finder.modules.items():
        if mod.__file__ is None:
            continue
        assert os.path.exists(mod.__file__)
        results.append(env.File(mod.__file__))
    return results

python_scanner = SCons.Scanner.Scanner(function = python_scan, skeys = ['.py'])


def code_generate(env, script, target, source, command):
    """Method to simplify code generation via python scripts.

    http://www.scons.org/wiki/UsingCodeGenerators
    http://www.scons.org/doc/0.98.5/HTML/scons-user/c2768.html
    """

    # We're generating code using Python scripts, so we have to be
    # careful with our scons elements.  This entry represents
    # the generator file *in the source directory*.
    script_src = env.File(script).srcnode()

    # This command creates generated code *in the build directory*.
    command = command.replace('$SCRIPT', script_src.path)
    action = SCons.Action.Action(command, "$CODEGENCOMSTR")
    code = env.Command(target, source, action)

    # Explicitly mark that the generated code depends on the generator,
    # and on implicitly imported python modules
    path = (script_src.get_dir(),) if scons_version < (2, 5, 0) else lambda x: script_src
    deps = [script_src]
    deps += script_src.get_implicit_deps(env, python_scanner, path)
    env.Depends(code, deps)

    # Running the Python script causes .pyc files to be generated in the
    # source directory.  When we clean up, they should go too. So add side
    # effects for .pyc files
    for dep in deps:
        pyc = env.File(str(dep) + 'c')
        env.SideEffect(pyc, code)

    return code


def createCodeGenerateMethod(env):
    env.Append(SCANNERS = python_scanner)
    env.AddMethod(code_generate, 'CodeGenerate')


def _pkg_check_modules(env, name, modules):
    '''Simple wrapper for pkg-config.'''

    env['HAVE_' + name] = False

    # For backwards compatability
    env[name.lower()] = False

    if env['platform'] == 'windows':
        return

    if not env.Detect('pkg-config'):
        return

    if subprocess.call(["pkg-config", "--exists", ' '.join(modules)]) != 0:
        return

    # Strip version expressions from modules
    modules = [module.split(' ', 1)[0] for module in modules]

    # Other flags may affect the compilation of unrelated targets, so store
    # them with a prefix, (e.g., XXX_CFLAGS, XXX_LIBS, etc)
    try:
        flags = env.ParseFlags('!pkg-config --cflags --libs ' + ' '.join(modules))
    except OSError:
        return
    prefix = name + '_'
    for flag_name, flag_value in flags.items():
        assert '_' not in flag_name
        env[prefix + flag_name] = flag_value

    env['HAVE_' + name] = True

def pkg_check_modules(env, name, modules):

    sys.stdout.write('Checking for %s (%s)...' % (name, ' '.join(modules)))
    _pkg_check_modules(env, name, modules)
    result = env['HAVE_' + name]
    sys.stdout.write(' %s\n' % ['no', 'yes'][int(bool(result))])

    # XXX: For backwards compatability
    env[name.lower()] = result


def pkg_use_modules(env, names):
    '''Search for all environment flags that match NAME_FOO and append them to
    the FOO environment variable.'''

    names = env.Flatten(names)

    for name in names:
        prefix = name + '_'

        if not 'HAVE_' + name in env:
            raise Exception('Attempt to use unknown module %s' % name)

        if not env['HAVE_' + name]:
            raise Exception('Attempt to use unavailable module %s' % name)

        flags = {}
        for flag_name, flag_value in env.Dictionary().items():
            if flag_name.startswith(prefix):
                flag_name = flag_name[len(prefix):]
                if '_' not in flag_name:
                    flags[flag_name] = flag_value
        if flags:
            env.MergeFlags(flags)


def createPkgConfigMethods(env):
    env.AddMethod(pkg_check_modules, 'PkgCheckModules')
    env.AddMethod(pkg_use_modules, 'PkgUseModules')


def parse_source_list(env, filename, names=None):
    # parse the source list file
    parser = source_list.SourceListParser()
    src = env.File(filename).srcnode()

    cur_srcdir = env.Dir('.').srcnode().abspath
    top_srcdir = env.Dir('#').abspath
    top_builddir = os.path.join(top_srcdir, env['build_dir'])

    # Normalize everything to / slashes
    cur_srcdir = cur_srcdir.replace('\\', '/')
    top_srcdir = top_srcdir.replace('\\', '/')
    top_builddir = top_builddir.replace('\\', '/')

    # Populate the symbol table of the Makefile parser.
    parser.add_symbol('top_srcdir', top_srcdir)
    parser.add_symbol('top_builddir', top_builddir)

    sym_table = parser.parse(src.abspath)

    if names:
        if isinstance(names, basestring):
            names = [names]

        symbols = names
    else:
        symbols = list(sym_table.keys())

    # convert the symbol table to source lists
    src_lists = {}
    for sym in symbols:
        val = sym_table[sym]
        srcs = []
        for f in val.split():
            if f:
                # Process source paths
                if f.startswith(top_builddir + '/src'):
                    # Automake puts build output on a `src` subdirectory, but
                    # SCons does not, so strip it here.
                    f = top_builddir + f[len(top_builddir + '/src'):]
                if f.startswith(cur_srcdir + '/'):
                    # Prefer relative source paths, as absolute files tend to
                    # cause duplicate actions.
                    f = f[len(cur_srcdir + '/'):]
                # do not include any headers
                if f.endswith(tuple(['.h','.hpp','.inl'])):
                    continue
                srcs.append(f)

        src_lists[sym] = srcs

    # if names are given, concatenate the lists
    if names:
        srcs = []
        for name in names:
            srcs.extend(src_lists[name])

        return srcs
    else:
        return src_lists

def createParseSourceListMethod(env):
    env.AddMethod(parse_source_list, 'ParseSourceList')


def generate(env):
    """Common environment generation code"""

    verbose = env.get('verbose', False) or not env.get('quiet', True)
    if not verbose:
        quietCommandLines(env)

    # Custom builders and methods
    createConvenienceLibBuilder(env)
    createCodeGenerateMethod(env)
    createPkgConfigMethods(env)
    createParseSourceListMethod(env)

    # for debugging
    #print env.Dump()


def exists(env):
    return 1
