#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

"""
python-qpid-proton setup script

DISCLAIMER: This script took lots of inspirations from PyZMQ, which is licensed
under the 'MODIFIED BSD LICENSE'.

Although inspired by the work in PyZMQ, this script and the modules it depends
on were largely simplified to meet the requirements of the library.

The default behavior of this script is to build the registered `_cproton`
extension using the system qpid-proton library. However, before doing that, the
script will try to discover the available qpid-proton's version and whether it's
suitable for the version of this library. This allows us to have a tight release
between the versions of the bindings and qpid-proton's version.

The versions used to verify this are in `setuputils.bundle` and they should be
increased on every release. Note that `bundled_version` matches the current
released version. The motivation behind this is that we don't know how many
new releases will be made in the `0.9` series, therefore we need to target the
latest possible.

If qpid-proton is found in the system and the available versions are match the
required ones, then the install process will continue normally.

If the available versions are not good for the bindings or the library is
missing, then the following will happen:

The setup script will attempt to download the C source for qpid-proton - see
`setuputils.bundle.fetch_libqpid_proton` - and it will include the proton C
code into the extension itself.

While the above removes the need of *always* having qpid-proton installed, it
does not solve the need of having `swig` and the libraries qpid-proton requires
installed to make this setup work.

From the Python side, this scripts overrides 1 command - build_ext - and it adds a
new one. The later - Configure - is called from the former to setup/discover what's
in the system. The rest of the comands and steps are done normally without any kind
of monkey patching.
"""

import glob
import os
import subprocess
import sys

import distutils.spawn as ds_spawn
import distutils.sysconfig as ds_sys
from distutils.ccompiler import new_compiler, get_default_compiler
from distutils.core import setup, Extension
from distutils.command.build import build
from distutils.command.build_ext import build_ext
from distutils.command.sdist import sdist
from distutils import errors

from setuputils import bundle
from setuputils import log
from setuputils import misc


class CheckSDist(sdist):

    def run(self):
        self.distribution.run_command('configure')

        # Append the source that was removed during
        # the configuration step.
        _cproton = self.distribution.ext_modules[-1]
        _cproton.sources.append('cproton.i')

        try:
            sdist.run(self)
        finally:
            for src in ['cproton.py', 'cproton_wrap.c']:
                if os.path.exists(src):
                    os.remove(src)


class Configure(build_ext):
    description = "Discover Qpid Proton version"

    @property
    def compiler_type(self):
        compiler = self.compiler
        if compiler is None:
            return get_default_compiler()
        elif isinstance(compiler, str):
            return compiler
        else:
            return compiler.compiler_type

    def prepare_swig_wrap(self):
        """Run swig against the sources.  This will cause swig to compile the
        cproton.i file into a .c file called cproton_wrap.c, and create
        cproton.py.
        """
        ext = self.distribution.ext_modules[-1]

        if 'SWIG' in os.environ:
            self.swig = os.environ['SWIG']

        try:
            # This will actually call swig to generate the files
            # and list the sources.
            self.swig_sources(ext.sources, ext)
        except (errors.DistutilsExecError, errors.DistutilsPlatformError) as e:
            if not (os.path.exists('cproton_wrap.c') or
                    os.path.exists('cproton.py')):
                raise e

        # now remove the cproton.i file from the source list so we don't run
        # swig again.
        ext.sources = ext.sources[1:]
        ext.swig_opts = []

    def bundle_libqpid_proton_extension(self):
        """The proper version of libqpid-proton is not present on the system,
        so attempt to retrieve the proper libqpid-proton sources and
        include them in the extension.
        """
        setup_path = os.path.dirname(os.path.realpath(__file__))
        base = self.get_finalized_command('build').build_base
        build_include = os.path.join(base, 'include')

        log.info("Bundling qpid-proton into the extension")

        # QPID_PROTON_SRC - (optional) pathname to the Proton C sources.  Can
        # be used to override where this setup gets the Proton C sources from
        # (see bundle.fetch_libqpid_proton())
        if 'QPID_PROTON_SRC' not in os.environ:
            if not os.path.exists(os.path.join(setup_path, 'CMakeLists.txt')):
                bundledir = os.path.join(base, "bundled")
                if not os.path.exists(bundledir):
                    os.makedirs(bundledir)
                bundle.fetch_libqpid_proton(bundledir)
                libqpid_proton_dir = os.path.abspath(os.path.join(bundledir, 'qpid-proton'))
            else:
                # setup.py is being invoked from within the proton source tree
                # (CMakeLists.txt is not present in the python source dist).
                # In this case build using the local sources.  This use case is
                # specifically for developers working on the proton source
                # code.
                proton_c = os.path.join(setup_path, '..', '..', '..')
                libqpid_proton_dir = os.path.abspath(proton_c)
        else:
            libqpid_proton_dir = os.path.abspath(os.environ['QPID_PROTON_SRC'])

        log.debug("Using libqpid-proton src: %s" % libqpid_proton_dir)

        proton_base = os.path.join(libqpid_proton_dir, 'proton-c')
        proton_src = os.path.join(proton_base, 'src')
        proton_include = os.path.join(proton_base, 'include')

        #
        # Create any generated header files, and put them in build_include:
        #
        if not os.path.exists(build_include):
            os.makedirs(build_include)
            os.mkdir(os.path.join(build_include, 'proton'))

        # Generate `protocol.h` by calling the python
        # script found in the source dir.
        with open(os.path.join(build_include, 'protocol.h'), 'wb') as header:
            subprocess.Popen([sys.executable, os.path.join(proton_src, 'protocol.h.py')],
                              env={'PYTHONPATH': proton_base}, stdout=header)

        # Generate `encodings.h` by calling the python
        # script found in the source dir.
        with open(os.path.join(build_include, 'encodings.h'), 'wb') as header:
            subprocess.Popen([sys.executable,
                              os.path.join(proton_src, 'codec', 'encodings.h.py')],
                              env={'PYTHONPATH': proton_base}, stdout=header)

        # Create a custom, temporary, version.h file mapping the
        # major and minor versions from the downloaded tarball. This version should
        # match the ones in the bundle module
        with open(os.path.join(build_include, 'proton', 'version.h'), "wb") as ver:
            version_text = """
#ifndef _PROTON_VERSION_H
#define _PROTON_VERSION_H 1
#define PN_VERSION_MAJOR %i
#define PN_VERSION_MINOR %i
#define PN_VERSION_POINT %i
#endif /* version.h */
""" % bundle.bundled_version
            ver.write(version_text.encode('utf-8'))

        # Collect all the Proton C files that need to be built.
        # we could've used `glob(.., '*', '*.c')` but I preferred going
        # with an explicit list of subdirs that we can control and expand
        # depending on the version. Specifically, lets avoid adding things
        # we don't need.

        sources = []
        for subdir in ['object', 'framing', 'codec', 'dispatcher',
                       'engine', 'events', 'transport',
                       'message', 'reactor', 'messenger',
                       'handlers', 'posix']:

            sources.extend(glob.glob(os.path.join(proton_src, subdir, '*.c')))

        sources.extend(filter(lambda x: not x.endswith('dump.c'),
                       glob.iglob(os.path.join(proton_src, '*.c'))))

        # Look for any optional libraries that proton needs, and adjust the
        # source list and compile flags as necessary.
        libraries = []

        # -D flags (None means no value, just define)
        macros=[('qpid_proton_EXPORTS', None),
                ('USE_ATOLL', None),
                ('USE_STRERROR_R', None)]

        # Check whether openssl is installed by poking
        # pkg-config for a minimum version 0. If it's installed, it should
        # return True and we'll use it. Otherwise, we'll use the stub.
        if misc.pkg_config_version(atleast='0', module='openssl'):
            libraries += ['ssl', 'crypto']
            sources.append(os.path.join(proton_src, 'ssl', 'openssl.c'))
        else:
            sources.append(os.path.join(proton_src, 'ssl', 'ssl_stub.c'))

        # create a temp compiler to check for optional compile-time features
        cc = new_compiler(compiler=self.compiler_type)
        cc.output_dir = self.build_temp

        # Some systems need to link to `rt`. Check whether `clock_gettime` is
        # around and if librt is needed
        if cc.has_function('clock_gettime'):
            macros.append(('USE_CLOCK_GETTIME', None))
        else:
            if cc.has_function('clock_gettime', libraries=['rt']):
                libraries.append('rt')
                macros.append(('USE_CLOCK_GETTIME', None))

        # 0.10 added an implementation for cyrus. Check
        # if it is available before adding the implementation to the sources
        # list. Eventually, `sasl.c` will be added and one of the existing
        # implementations will be used.
        if cc.has_function('sasl_client_done', includes=['sasl/sasl.h'],
                           libraries=['sasl2']):
            libraries.append('sasl2')
            sources.append(os.path.join(proton_src, 'sasl', 'cyrus_sasl.c'))
        else:
            sources.append(os.path.join(proton_src, 'sasl', 'none_sasl.c'))

        sources.append(os.path.join(proton_src, 'sasl', 'sasl.c'))

        # compile all the proton sources.  We'll add the resulting list of
        # objects to the _cproton extension as 'extra objects'.  We do this
        # instead of just lumping all the sources into the extension to prevent
        # any proton-specific compilation flags from affecting the compilation
        # of the generated swig code

        cc = new_compiler(compiler=self.compiler_type)
        ds_sys.customize_compiler(cc)

        objects = cc.compile(sources,
                             macros=macros,
                             include_dirs=[build_include,
                                           proton_include,
                                           proton_src],
                             # compiler command line options:
                             extra_postargs=['-std=gnu99'],
                             output_dir=self.build_temp)

        #
        # Now update the _cproton extension instance to include the objects and
        # libraries
        #
        _cproton = self.distribution.ext_modules[-1]
        _cproton.extra_objects = objects
        _cproton.include_dirs.append(build_include)
        _cproton.include_dirs.append(proton_include)

        # swig will need to access the proton headers:
        _cproton.swig_opts.append('-I%s' % build_include)
        _cproton.swig_opts.append('-I%s' % proton_include)

        # lastly replace the libqpid-proton dependency with libraries required
        # by the Proton objects:
        _cproton.libraries=libraries

    def check_qpid_proton_version(self):
        """check the qpid_proton version"""

        target_version = bundle.bundled_version_str
        return (misc.pkg_config_version(max_version=target_version) and
                misc.pkg_config_version(atleast=bundle.min_qpid_proton_str))

    @property
    def bundle_proton(self):
        """Need to bundle proton if the conditions below are met."""
        return ('QPID_PROTON_SRC' in os.environ) or \
            (not self.check_qpid_proton_version())

    def use_installed_proton(self):
        """The Proton development headers and library are installed, update the
        _cproton extension to tell it where to find the library and headers.
        """
        _cproton = self.distribution.ext_modules[-1]
        incs = misc.pkg_config_get_var('includedir')
        for i in incs.split():
            _cproton.swig_opts.append('-I%s' % i)
            _cproton.include_dirs.append(i)
        ldirs = misc.pkg_config_get_var('libdir')
        _cproton.library_dirs.extend(ldirs.split())

    def run(self):
        # check if the Proton library and headers are installed and are
        # compatible with this version of the binding.
        if self.bundle_proton:
            # Proton not installed or compatible
            self.bundle_libqpid_proton_extension()
        else:
            self.use_installed_proton()
        self.prepare_swig_wrap()


class CustomBuildOrder(build):
    # The sole purpose of this class is to re-order
    # the commands execution so that `build_ext` is executed *before*
    # build_py. We need this to make sure `cproton.py` is generated
    # before the python modules are collected. Otherwise, it won't
    # be installed.
    sub_commands = [
        ('build_ext', build.has_ext_modules),
        ('build_py', build.has_pure_modules),
        ('build_clib', build.has_c_libraries),
        ('build_scripts', build.has_scripts),
    ]


class CheckingBuildExt(build_ext):
    """Subclass build_ext to build qpid-proton using `cmake`"""

    def run(self):
        # Discover qpid-proton in the system
        self.distribution.run_command('configure')
        build_ext.run(self)


# Override `build_ext` and add `configure`
cmdclass = {'configure': Configure,
            'build': CustomBuildOrder,
            'build_ext': CheckingBuildExt,
            'sdist': CheckSDist}

setup(name='python-qpid-proton',
      version=bundle.bundled_version_str,
      description='An AMQP based messaging library.',
      author='Apache Qpid',
      author_email='proton@qpid.apache.org',
      url='http://qpid.apache.org/proton/',
      packages=['proton'],
      py_modules=['cproton'],
      license="Apache Software License",
      classifiers=["License :: OSI Approved :: Apache Software License",
                   "Intended Audience :: Developers",
                   "Programming Language :: Python",
                   "Programming Language :: Python :: 2",
                   "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"],
      cmdclass=cmdclass,
      # Note well: the following extension instance is modified during the
      # installation!  If you make changes below, you may need to update the
      # Configure class above
      ext_modules=[Extension('_cproton',
                             sources=['cproton.i', 'cproton_wrap.c'],
                             swig_opts=['-threads'],
                             extra_compile_args=['-pthread'],
                             libraries=['qpid-proton'])])
