# -*- python -*-
import SCons.Errors

import cenv
import platform
from modules import add_python_module_funcs_to_env
from utils import is_building

Import('env')

AddOption('--dumpenv', dest='dumpenv', action='store_true', default=False, help='Dump environment')
AddOption('--vars', dest='vars', type='string', nargs=1, action='store', metavar='FILE', help='Variables file to use')
vars = cenv.init_global_variables(GetOption('vars'), ARGUMENTS)
env = SConscript('vars.scons', exports='env')
env.MergeFlags(env['XFLAGS'])


def ar_command(cmd, target, source, env):
    from response_file import gen_rsp_file
    path = target[0].abspath + ".rsp"
    gen_rsp_file([File(path)], source, env)
    env['_RSP_FILE'] = path
    from SCons.Action import CommandAction
    act = CommandAction(cmd)
    return act.execute(target, source, env)


def ar_mri_command(target, source, env):
    path = target[0].abspath + ".rsp"  # not really a response file, but still
    with open(path, "w") as f:
        f.write("CREATE {}\n".format(target[0].abspath))
        for s in source:
            f.write("ADDMOD {}\n".format(s.abspath))
        f.write("SAVE\n")
        f.write("END\n")
    from SCons.Action import CommandAction
    act = CommandAction("$AR -M < {}".format(path))
    return act.execute(target, source, env)


def make_ar_command(prev_cmd):
    from functools import partial
    return partial(ar_command, prev_cmd.replace('$SOURCES', '@$_RSP_FILE'))


if env.get('BUILD_PATH') and env.get('PYTHON_SOURCE_PATH'):
    print("Using Python sources from {}".format(env.Dir('$PYTHON_SOURCE_PATH').abspath))

    add_python_module_funcs_to_env(env)

    # Put SCons' database in our build directory.
    env.SConsignFile('$BUILD_PATH/sconsign')

    # Mount Python sources under our project root and make sure all targets that come from these sources go to
    # our build directory.
    env.Dir('#python').addRepository(env.Dir('$PYTHON_SOURCE_PATH'))
    # Now create point all build artifcats from the Python source tree to $BUILD_PATH/python
    env.VariantDir('$BUILD_PATH/python', '#python')

    # Run our configure-equivalent code so we can create pyconfig.h, Makefile, etc.
    env, pyconfig_defines = env.SConscript('configure.scons', exports='env')

    # We create a response file (a file with all the list of objects) so it won't pass the max arg len limit
    # This is true for some of the Linuxes and also Windows.
    if platform.dist()[:2] == ('centos', '4.8'):
        env['ARCOM'] = ar_mri_command
    elif pyconfig_defines.get('AR_HAS_RSP', False):
        env['ARCOM'] = make_ar_command(env['ARCOM'])

    # Add Python's (mounted) Include directory to our include path.
    env.Append(CPPPATH=['#python/Include', '$BUILD_PATH'])
    if env['PLATFORM'] == 'win32':
        env.Append(CPPPATH=['#python/PC'])

    # # These kwargs will get passed to child scripts (less typing):
    default_sconscript_kwargs = dict(exports='env pyconfig_defines', variant_dir=env.Dir('$BUILD_PATH'), duplicate=False)

    # Configure stage: create pyconfig.h and Makefile, needed for building Python and creating _sysconfigdata.py
    pyconfig = env.SConscript('pyconfig.scons', **default_sconscript_kwargs)
    makefile = env.SConscript('makefile.scons', **default_sconscript_kwargs)
    configure = Alias('configure', [pyconfig, makefile])

    # build standard C modules:
    standard_python_c_modules = env.SConscript('standard_c_modules.scons', **default_sconscript_kwargs)

    # Create Modules/config.c with all the C modules
    env.AppendPythonModulesConfiguration(standard_python_c_modules)

    # Create a libpython that contains all the core python code, but doesn't include any static C modules or config.c.
    libpython, libpython_objects = env.SConscript('libpython.scons', **default_sconscript_kwargs)
    default_sconscript_kwargs['exports'] += ' libpython libpython_objects'

    # python.o is shared both by "bare bones" python and "full" python.
    python_o = SConscript("standalone_python.scons", **default_sconscript_kwargs)
    default_sconscript_kwargs['exports'] += ' python_o'

    # Create a "bare bones" Python that doesn't freeze any module, and also _sysconfigdata.py files.
    bare_python = SConscript('barepython.scons', **default_sconscript_kwargs)
    default_sconscript_kwargs['exports'] += ' bare_python'

    # Freeze Python's stdlib modules:
    freeze_modules = SConscript("freeze_stdlib.scons", **default_sconscript_kwargs)
    default_sconscript_kwargs['exports'] += ' freeze_modules'

    if env.get('EXTERNAL_C_MODULES_FILE'):
        external_python_c_modules = env.SConscript('external_c_modules.scons', **default_sconscript_kwargs)
        env.AppendPythonModulesConfiguration(external_python_c_modules)

    if env.get('EXTERNAL_PY_MODULES_FILE'):
        freeze_modules = env.SConscript('external_py_modules.scons', **default_sconscript_kwargs)

    # Finalize freezing by creating the import file that declares PyImport_FrozenModules
    freeze_modules = SConscript("finalize_py_modules.scons", **default_sconscript_kwargs)

    # Pack a full Python library that can later be used by other projects
    libfullpython = SConscript('libfullpython.scons', **default_sconscript_kwargs)
    Alias('libfullpython', libfullpython)
    default_sconscript_kwargs['exports'] += ' libfullpython'

    # Create a full python executable for fun and games
    fullpython = SConscript('fullpython.scons', **default_sconscript_kwargs)

    if GetOption('dumpenv'):
        print(env.Dump())
elif is_building():
    print("Error: to build you have to pass BUILD_PATH and PYTHON_SOURCE_PATH either in command line or a vars file (--vars)")


# TODO: help
Help("""
type:
 scons configure
""")
Help("Variables you can set either from command line or by using the --vars=file option:\n")
Help(vars.GenerateHelpText(env))