#!/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 commands 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_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 packaged in the sdist and strip out
        # anything windows and configuration-dependent

        sources = []
        cfgdep = ['openssl.c',
                  'schannel.c',
                  'ssl_stub.c',
                  'cyrus_sasl.c',
                  'cyrus_stub.c',
                  'snprintf.c']

        stripdirs = ['proactor',
                     'msvc',
                     'windows']

        for root, dirs, files in os.walk(proton_src):
            for dir_ in stripdirs:
                if dir_ in dirs:
                    dirs.remove(dir_)

            for file_ in files:
                if file_.endswith('.c') and file_ not in cfgdep:
                    sources.append(os.path.join(root, file_))

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

        # -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']
            includes += [misc.pkg_config_get_var('openssl', 'includedir')]
            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:
            log.warn("Cyrus SASL not installed - only the ANONYMOUS and"
                     " PLAIN mechanisms will be supported!")
            sources.append(os.path.join(proton_src, 'sasl', 'cyrus_stub.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]+includes,
                             # 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='users@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",
                   "Programming Language :: Python :: 3.6"],
      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'])])
