#!/usr/bin/env python
#-*- coding: utf-8 -*-

import os
import sys
import subprocess
import textwrap
import warnings
from functools import partial
from distutils.sysconfig import get_python_inc

import setuptools
from setuptools import setup, Extension
from setuptools.command.test import test as TestCommand

MAJOR = 1
MINOR = 3
MICRO = 0
ISRELEASED = False
VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO)


# Return the git revision as a string
def git_version():
    def _minimal_ext_cmd(cmd):
        # construct minimal environment
        env = {}
        for k in ['SYSTEMROOT', 'PATH']:
            v = os.environ.get(k)
            if v is not None:
                env[k] = v
        # LANGUAGE is used on win32
        env['LANGUAGE'] = 'C'
        env['LANG'] = 'C'
        env['LC_ALL'] = 'C'
        out = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                               env=env).communicate()[0]
        return out

    try:
        out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'])
        GIT_REVISION = out.strip().decode('ascii')
    except OSError:
        GIT_REVISION = "Unknown"

    return GIT_REVISION


def get_version_info():
    # Adding the git rev number needs to be done inside
    # write_version_py(), otherwise the import of pywt.version messes
    # up the build under Python 3.
    FULLVERSION = VERSION
    if os.path.exists('.git'):
        GIT_REVISION = git_version()
    elif os.path.exists('pywt/version.py'):
        # must be a source distribution, use existing version file
        # load it as a separate module to not load pywt/__init__.py
        import types
        from importlib.machinery import SourceFileLoader
        loader = SourceFileLoader('pywt.version', 'pywt/version.py')
        version = types.ModuleType(loader.name)
        loader.exec_module(version)
        GIT_REVISION = version.git_revision
    else:
        GIT_REVISION = "Unknown"

    if not ISRELEASED:
        FULLVERSION += '.dev0+' + GIT_REVISION[:7]

    return FULLVERSION, GIT_REVISION


def write_version_py(filename='pywt/version.py'):
    cnt = """
# THIS FILE IS GENERATED FROM PYWAVELETS SETUP.PY
short_version = '%(version)s'
version = '%(version)s'
full_version = '%(full_version)s'
git_revision = '%(git_revision)s'
release = %(isrelease)s

if not release:
    version = full_version
"""
    FULLVERSION, GIT_REVISION = get_version_info()

    with open(filename, 'w') as a:
        a.write(cnt % {'version': VERSION,
                       'full_version': FULLVERSION,
                       'git_revision': GIT_REVISION,
                       'isrelease': str(ISRELEASED)})


# BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
# update it when the contents of directories change.
if os.path.exists('MANIFEST'):
    os.remove('MANIFEST')


if sys.platform == "darwin":
    # Don't create resource files on OS X tar.
    os.environ["COPY_EXTENDED_ATTRIBUTES_DISABLE"] = "true"
    os.environ["COPYFILE_DISABLE"] = "true"


make_ext_path = partial(os.path.join, "pywt", "_extensions")

sources = ["c/common.c", "c/convolution.c", "c/wt.c", "c/wavelets.c", "c/cwt.c"]
sources = list(map(make_ext_path, sources))
source_templates = ["c/convolution.template.c", "c/wt.template.c", "c/cwt.template.c"]
source_templates = list(map(make_ext_path, source_templates))
headers = ["c/templating.h", "c/wavelets_coeffs.h",
            "c/common.h", "c/convolution.h", "c/wt.h", "c/wavelets.h", "c/cwt.h"]
headers = list(map(make_ext_path, headers))
header_templates = ["c/convolution.template.h", "c/wt.template.h",
                    "c/wavelets_coeffs.template.h", "c/cwt.template.h"]
header_templates = list(map(make_ext_path, header_templates))


def get_cython_sources(use_cython):
    cython_modules = ['_pywt', '_dwt', '_swt', '_cwt']
    cython_sources = [('{0}.pyx' if use_cython else '{0}.c').format(module)
                      for module in cython_modules]
    return cython_modules, cython_sources


c_macros = [("PY_EXTENSION", None), ]
cython_macros = []

#c99_test_c = """#include <complex.h>
#int main(int argc, char** argv) { float complex a;  return(0); }"""

if 'USE_C99_COMPLEX' in os.environ:
    use_c99 = bool(int(os.environ['USE_C99_COMPLEX']))
else:
    # default to False on non-posix platforms
    # (MSVC doesn't support C99 complex)
    if os.name == 'posix':
        use_c99 = True
    else:
        use_c99 = False
if use_c99:
    c_macros += [("HAVE_C99_COMPLEX", None), ]
    # avoid compiler warnings:  tell Cython to use C99 complex types
    cython_macros += [('CYTHON_CCOMPLEX', 1), ]
    pxi_defines = dict(HAVE_C99_CPLX=1)
    py_defines = dict(_have_c99_complex=1)
else:
    pxi_defines = dict(HAVE_C99_CPLX=0)
    py_defines = dict(_have_c99_complex=0)

# write a file config.pxi that can be included by other .pyx files to determine
# whether or not C99 complex is supported at compile-time
defines_pxi = os.path.join(
    os.path.dirname(__file__), 'pywt', '_extensions', 'config.pxi')
with open(defines_pxi, 'w') as fd:
    fd.write("# Autogenerated file containing Cython compile-time defines\n\n")
    for k, v in pxi_defines.items():
        fd.write('DEF %s = %d\n' % (k.upper(), int(v)))

defines_py = os.path.join(
    os.path.dirname(__file__), 'pywt', '_c99_config.py')
with open(defines_py, 'w') as fd:
    fd.write("# Autogenerated file containing compile-time definitions\n\n")
    for k, v in py_defines.items():
        fd.write('%s = %d\n' % (k, int(v)))

cythonize_opts = {'language_level': '3'}
if os.environ.get("CYTHON_TRACE"):
    cythonize_opts['linetrace'] = True
    cython_macros.append(("CYTHON_TRACE_NOGIL", 1))

# By default C object files are rebuilt for every extension
# C files must be built once only for coverage to work
c_lib = ('c_wt', {'sources': sources,
                  'depends': source_templates + header_templates + headers,
                  'include_dirs': [make_ext_path("c"), get_python_inc()],
                  'macros': c_macros, })

def get_ext_modules(use_cython):
    from numpy import get_include as get_numpy_include
    cython_modules, cython_sources = get_cython_sources(use_cython)
    ext_modules = [
        Extension('pywt._extensions.{0}'.format(module),
                  sources=[make_ext_path(source)],
                  # Doesn't automatically rebuild if library changes
                  depends=c_lib[1]['sources'] + c_lib[1]['depends'],
                  include_dirs=[make_ext_path("c"), get_numpy_include()],
                  define_macros=c_macros + cython_macros,
                  libraries=[c_lib[0]],)
        for module, source, in zip(cython_modules, cython_sources)
    ]
    return ext_modules


from setuptools.command.develop import develop
class develop_build_clib(develop):
    """Ugly monkeypatching to get clib to build for development installs

    See coverage comment above for why we don't just let libraries be built
    via extensions.

    All this is a copy of the relevant part of `install_for_development`
    for current master (Sep 2016) of setuptools.

    Note: if you want to build in-place with ``python setup.py build_ext``,