import os
import re
import sys

# This import is apparently needed for Nose on Red Hat's Python
import multiprocessing

from distutils.command.build_ext import build_ext
from distutils.errors import (CCompilerError, DistutilsExecError,
                              DistutilsPlatformError)

from setuptools import setup, Extension, Feature

cmdclass = {}
PYPY = hasattr(sys, 'pypy_version_info')
JYTHON = sys.platform.startswith('java')
requirements = []

if sys.version_info[0] == 2 or (sys.version_info[0] == 3
                                and sys.version_info[1] < 3):
    requirements.append('ipaddress')

compile_args = ['-Wall', '-Wextra']

if sys.version_info[0] == 2:
    compile_args.append('-fno-strict-aliasing')

ext_module = [
    Extension(
        'maxminddb.extension',
        libraries=['maxminddb'],
        sources=['maxminddb/extension/maxminddb.c'],
        extra_compile_args=compile_args,
    )
]

# Cargo cult code for installing extension with pure Python fallback.
# Taken from SQLAlchemy, but this same basic code exists in many modules.
ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
if sys.platform == 'win32':
    # 2.6's distutils.msvc9compiler can raise an IOError when failing to
    # find the compiler
    ext_errors += (IOError, )


class BuildFailed(Exception):
    def __init__(self):
        self.cause = sys.exc_info()[1]  # work around py 2/3 different syntax


class ve_build_ext(build_ext):
    # This class allows C extension building to fail.

    def run(self):
        try:
            build_ext.run(self)
        except DistutilsPlatformError:
            raise BuildFailed()

    def build_extension(self, ext):
        try:
            build_ext.build_extension(self, ext)
        except ext_errors:
            raise BuildFailed()
        except ValueError:
            # this can happen on Windows 64 bit, see Python issue 7511
            if "'path'" in str(sys.exc_info()[1]):  # works with both py 2/3
                raise BuildFailed()
            raise


cmdclass['build_ext'] = ve_build_ext

#

ROOT = os.path.dirname(__file__)

with open(os.path.join(ROOT, 'README.rst'), 'rb') as fd:
    README = fd.read().decode('utf8')

with open(os.path.join(ROOT, 'maxminddb', '__init__.py'), 'rb') as fd:
    maxminddb_text = fd.read().decode('utf8')
    LICENSE = re.compile(r".*__license__ = '(.*?)'",
                         re.S).match(maxminddb_text).group(1)
    VERSION = re.compile(r".*__version__ = '(.*?)'",
                         re.S).match(maxminddb_text).group(1)


def status_msgs(*msgs):
    print('*' * 75)
    for msg in msgs:
        print(msg)
    print('*' * 75)


def find_packages(location):
    packages = []
    for pkg in ['maxminddb']:
        for _dir, subdirectories, files in (os.walk(
                os.path.join(location, pkg))):
            if '__init__.py' in files:
                tokens = _dir.split(os.sep)[len(location.split(os.sep)):]
                packages.append(".".join(tokens))
    return packages


def run_setup(with_cext):
    kwargs = {}
    if with_cext:
        if Feature:
            kwargs['features'] = {
                'extension':
                Feature(
                    "optional C implementation",
                    standard=True,
                    ext_modules=ext_module)
            }
        else:
            kwargs['ext_modules'] = ext_module

    setup(
        name='maxminddb',
        version=VERSION,
        author='Gregory Oschwald',
        author_email='goschwald@maxmind.com',
        description='Reader for the MaxMind DB format',
        long_description=README,
        url='http://www.maxmind.com/',
        packages=find_packages('.'),
        package_data={'': ['LICENSE']},
        package_dir={'maxminddb': 'maxminddb'},
        include_package_data=True,
        install_requires=requirements,
        tests_require=['nose'],
        test_suite='nose.collector',
        license=LICENSE,
        cmdclass=cmdclass,
        classifiers=[
            'Development Status :: 5 - Production/Stable',
            'Environment :: Web Environment',
            'Intended Audience :: Developers',
            'Intended Audience :: System Administrators',
            'License :: OSI Approved :: Apache Software License',
            'Programming Language :: Python :: 2.6',
            'Programming Language :: Python :: 2.7',
            'Programming Language :: Python :: 3',
            'Programming Language :: Python :: 3.3',
            'Programming Language :: Python :: 3.4',
            'Programming Language :: Python :: 3.5',
            'Programming Language :: Python',
            'Topic :: Internet :: Proxy Servers',
            'Topic :: Internet',
        ],
        **kwargs)


if PYPY or JYTHON:
    run_setup(False)
    status_msgs("WARNING: Disabling C extension due to Python platform.",
                "Plain-Python build succeeded.")
else:
    try:
        run_setup(True)
    except BuildFailed as exc:
        status_msgs(exc.cause,
                    "WARNING: The C extension could not be compiled, " +
                    "speedups are not enabled.",
                    "Failure information, if any, is above.",
                    "Retrying the build without the C extension now.")

        run_setup(False)

        status_msgs("WARNING: The C extension could not be compiled, " +
                    "speedups are not enabled.",
                    "Plain-Python build succeeded.")
