""" Cython-based Python Module for Python 3 """
from buildutils import *

Import('env', 'build', 'install')

localenv = env.Clone()


def configure_numpy(python_command):
    script = '\n'.join(("from distutils.sysconfig import *",
                        "import numpy",
                        "print(get_config_var('SO'))",
                        "print(get_python_version())",
                        "print(numpy.get_include())"))
    info = getCommandOutput(python_command, '-c', script)
    module_ext, py_version, numpy_include = info.splitlines()[-3:]

    incDirs = (".", "../../include", numpy_include,
               localenv['sundials_include'], localenv['boost_inc_dir'])
    localenv['py_include_dirs'] = repr([x for x in incDirs if x])

    return module_ext, py_version


def add_dependencies(mod, ext):
    localenv.Depends(mod, ext)
    localenv.Depends(ext, localenv['cantera_staticlib'])
    localenv.Depends(mod, dataFiles + testFiles + scripts)
    for f in mglob(localenv, 'cantera', 'pyx', 'pxd'):
        localenv.Depends(ext, f)

    for f in (mglob(localenv, 'cantera/test', 'py') +
              mglob(localenv, 'cantera/mixmaster', 'py') +
              mglob(localenv, 'cantera/mixmaster/Units', 'py') +
              mglob(localenv, 'cantera/examples/tutorial', 'py') +
              mglob(localenv, 'cantera/examples/equilibrium', 'py') +
              mglob(localenv, 'cantera/examples/kinetics', 'py') +
              mglob(localenv, 'cantera/examples/transport', 'py') +
              mglob(localenv, 'cantera/examples/reactors', 'py') +
              mglob(localenv, 'cantera/examples/onedim', 'py') +
              mglob(localenv, 'cantera/examples/surface_chemistry', 'py') +
              mglob(localenv, 'cantera/examples/misc', 'py')):
        localenv.Depends(mod, f)

script_ext = '.py' if os.name == 'nt' else ''
localenv['py_ctml_writer'] = repr('scripts/ctml_writer%s' % script_ext)
localenv['py_ck2cti'] = repr('scripts/ck2cti%s' % script_ext)
localenv['py_mixmaster'] = repr('scripts/mixmaster%s' % script_ext)

# The actual ctml_writer and ck2cti scripts
build(env.Command('cantera/ctml_writer.py',
                  '#interfaces/python/ctml_writer.py',
                  Copy('$TARGET', '$SOURCE')))
build(env.Command('cantera/ck2cti.py',
                  '#interfaces/python/ck2cti.py',
                  Copy('$TARGET', '$SOURCE')))

# thin wrappers
scripts = []
for script in mglob(env, 'scripts', 'py.in'):
  base_name = script.name.split('.')[0]
  script = build(env.Command('scripts/%s%s' % (base_name, script_ext), script,
                             Copy('$TARGET', '$SOURCE')))
  scripts.append(script)

def install_module(prefix, python_version):
    if prefix == 'USER':
        # Install to the OS-dependent user site-packages directory
        extra = '--user'
    elif prefix:
        # A specific location for the Cantera python module has been specified
        extra = '--prefix="%s"' % prefix
    else:
        # Install Python module in the default location
        extra = ''

    major = python_version[0]
    ver = '3' if major == '3' else ''
    dummy = 'dummy' + major
    if localenv['PYTHON_INSTALLER'] == 'direct':
        mod_inst = install(localenv.Command, dummy, mod,
                           build_cmd + ' install %s' % extra +
                           ' --record ../../build/python%s-installed-files.txt' % major)
        global_env = env
        def find_module_dir(target, source, env):
            check = pjoin('cantera','__init__.py')
            for filename in open('build/python%s-installed-files.txt' % major).readlines():
                filename = filename.strip()
                if filename.endswith(check):
                    filename = filename.replace(check,'')
                    global_env['python%s_module_loc' % ver] = os.path.normpath(filename)
                    break
        localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir))
        if not ver:
          env['install_python2_action'] = mod_inst

    elif localenv['PYTHON_INSTALLER'] == 'debian':
        install(localenv.Command, dummy, mod,
                build_cmd + ' install --install-layout=deb --no-compile %s' % extra)
        env['python%s_module_loc' % ver] = '<unspecified>'
    elif localenv['PYTHON_INSTALLER'] == 'binary':
        install(localenv.Command, dummy, mod,
                build_cmd + ' bdist_msi --dist-dir=../..' +
                ' --target-version=%s' % python_version)
        env['python%s_module_loc' % ver] = '<unspecified>'


libDirs = ('../../build/lib', localenv['sundials_libdir'],
           localenv['blas_lapack_dir'], localenv['boost_lib_dir'])
localenv['py_cantera_libs'] = repr(localenv['cantera_libs'])
localenv['py_libdirs'] = repr([x for x in libDirs if x])

# Compile the Python module with the same compiler as the rest of Cantera,
# unless otherwise specified
localenv['py_extra_compiler_args'] = repr([])
localenv['py_extra_link_args'] = repr([])
if localenv['OS'] == 'Windows':
    if env['CC'] == 'cl':
        flags = ['/EHsc']
        if env['debug']:
            flags.extend(['/Zi', '/Fd_cantera.pdb'])
            localenv['py_extra_link_args'] = repr(['/DEBUG'])
        compilerOpt = ' --compiler=msvc'
        localenv['py_extra_compiler_args'] = repr(flags)

    elif env['CC'] == 'gcc':
        compilerOpt = ' --compiler=mingw32'
else:
    compilerOpt = ''
    if '-fprofile-arcs' in localenv['CCFLAGS']:
        localenv['py_extra_compiler_args'] = repr(['-fprofile-arcs', '-ftest-coverage'])
        localenv['py_extra_link_args'] = repr(['-fprofile-arcs', '-ftest-coverage'])
    if  env['python_compiler']:
        localenv['ENV']['CC'] = env['python_compiler']
	localenv['ENV']['CXX'] = env['python_compiler']

if 'LDFLAGS' not in localenv['ENV']:
    localenv['ENV']['LDFLAGS'] = ''
for framework in localenv['FRAMEWORKS']:
    localenv['ENV']['LDFLAGS'] += ' -framework ' + framework

dataFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/data',
                                      '#build/data')
build(dataFiles)

testFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/test/data',
                                      '#test/data')
build(testFiles)

# Cython module for Python 3.x
if localenv['python3_package'] == 'y':
    module_ext, py3_version = configure_numpy(localenv['python3_cmd'])
    make_setup = localenv.SubstFile('#interfaces/cython/setup3.py',
                                    '#interfaces/cython/setup.py.in')
    build(make_setup)

    build_base = ('cd interfaces/cython &&'
                 ' $python3_cmd setup3.py %s'
                 ' --build-lib=../../build/python3'
                 ' --build-temp=../../build/temp-py3'
                 + compilerOpt)

    build_cmd = build_base % 'build'
    ext = build(localenv.Command('#build/python3/cantera/_cantera%s' % module_ext,
                                 'setup3.py',
                                 build_base % 'build_ext'))
    mod = build(localenv.Command('#build/python3/cantera/__init__.py',
                                 'setup3.py',
                                 build_cmd))
    env['python3_module'] = mod
    env['python3_extension'] = ext

    localenv.AddPreAction(ext, Delete('interfaces/cython/cantera/_cantera.cpp'))

    add_dependencies(mod, ext)
    install_module(localenv['python3_prefix'], py3_version)


# Cython module for Python 2.x
if localenv['python_package'] == 'new':
    module_ext, py2_version = configure_numpy(localenv['python_cmd'])
    make_setup = localenv.SubstFile('#interfaces/cython/setup2.py',
                                    '#interfaces/cython/setup.py.in')
    build(make_setup)

    build_base = ('cd interfaces/cython &&'
                 ' $python_cmd setup2.py %s'
                 ' --build-lib=../../build/python2'
                 ' --build-temp=../../build/temp-py2'
                 + compilerOpt)

    build_cmd = build_base % 'build'
    ext = build(localenv.Command('#build/python2/cantera/_cantera%s' % module_ext,
                                 'setup2.py',
                                 build_base % 'build_ext'))
    mod = build(localenv.Command('#build/python2/cantera/__init__.py',
                                 'setup2.py',
                                 build_cmd))
    env['python2_module'] = mod
    env['python2_extension'] = ext

    localenv.AddPreAction(ext, Delete('interfaces/cython/cantera/_cantera.cpp'))

    # Use 3to2 to convert examples from Python 3 syntax
    if env['python_convert_examples']:
        def convert_example(target, source, env):
            shutil.copyfile(source[0].abspath, target[0].abspath)
            subprocess.call(['3to2', '--no-diff', '-n', '-w','-x', 'str',
                             '-x', 'open', target[0].abspath])

        for subdir in subdirs('cantera/examples'):
            dirpath = pjoin('cantera', 'examples', subdir)
            for filename in os.listdir(dirpath):
                if not filename.endswith('.py'):
                    continue
                targetdir = '../../build/python2/cantera/examples'
                a = build(localenv.Command(pjoin(targetdir, subdir, filename),
                                           pjoin(dirpath, filename),
                                           convert_example))
                localenv.Depends(a, mod)

    add_dependencies(mod, ext)
    install_module(localenv['python_prefix'], py2_version)
