#!/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 behavior of this script is to build the registered `_cproton` extension
using the installed Qpid Proton C library and header files. If the library and
headers are not installed, or the installed version does not match the version
of these python bindings, then the script will attempt to build the extension
using the Proton C sources included in the python source distribution package.

While the above removes the need of *always* having Qpid Proton C development
files 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 latter - 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 log
from setuputils import misc


_PROTON_VERSION=(@PN_VERSION_MAJOR@,
                 @PN_VERSION_MINOR@,
                 @PN_VERSION_POINT@)
_PROTON_VERSION_STR = "%d.%d.%d" % _PROTON_VERSION


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 use_bundled_proton(self):
        """The proper version of libqpid-proton is not installed on the system,
        so use the included proton-c sources to build the extension
        """
        log.info("Building the bundled proton-c sources into 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')
        proton_base = os.path.abspath(os.path.join(setup_path, 'proton-c'))
        proton_src = os.path.join(proton_base, 'src')
        proton_include = os.path.join(proton_base, 'include')

        log.debug("Using Proton C sources: %s" % proton_base)

        # 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_installed('openssl', atleast='0'):
            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'))
            log.warn("OpenSSL not installed - disabling SSL support!")

        # 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'))
            log.warn("Cyrus SASL not installed - only the ANONYMOUS and"
                     " PLAIN mechanisms will be supported!")
        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 passed to setup 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 libqpid_proton_installed(self, version):
        """Check to see if the proper version of the Proton development library
        and headers are already installed
        """
        return misc.pkg_config_version_installed('libqpid-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.
        """
        # update the Extension instance passed to setup() to use the installed
        # headers and link library
        _cproton = self.distribution.ext_modules[-1]
        incs = misc.pkg_config_get_var('libqpid-proton', 'includedir')
        for i in incs.split():
            _cproton.swig_opts.append('-I%s' % i)
            _cproton.include_dirs.append(i)
        ldirs = misc.pkg_config_get_var('libqpid-proton', '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.libqpid_proton_installed(_PROTON_VERSION_STR):
            self.use_installed_proton()
        else:
            # Proton not installed or compatible, use bundled proton-c sources
            self.use_bundled_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=_PROTON_VERSION_STR + os.environ.get('PROTON_VERSION_SUFFIX', ''),
      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'])])
