# -*- coding: ascii -*-
#
# Copyright 2007 - 2013
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
 Main setup runner
===================

This module provides a wrapper around the distutils core setup.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"

import ConfigParser as _config_parser
from distutils import core as _core
import os as _os
import posixpath as _posixpath
import sys as _sys

from _setup import commands as _commands
from _setup import data as _data
from _setup import ext as _ext
from _setup import util as _util
from _setup import shell as _shell


def check_python_version(impl, version_min, version_max):
    """ Check python version """
    if impl == 'python':
        version_info = _sys.version_info
    elif impl == 'pypy':
        version_info = getattr(_sys, 'pypy_version_info', None)
        if not version_info:
            return
    elif impl == 'jython':
        if not 'java' in _sys.platform.lower():
            return
        version_info = _sys.version_info
    else:
        raise AssertionError("impl not in ('python', 'pypy', 'jython')")

    pyversion = map(int, version_info[:3])
    if version_min:
        min_required = \
            map(int, '.'.join((version_min, '0.0.0')).split('.')[:3])
        if pyversion < min_required:
            raise EnvironmentError("Need at least %s %s (vs. %s)" % (
                impl, version_min, '.'.join(map(str, pyversion))
            ))
    if version_max:
        max_required = map(int, version_max.split('.'))
        max_required[-1] += 1
        if pyversion >= max_required:
            raise EnvironmentError("Need at max %s %s (vs. %s)" % (
                impl,
                version_max,
                '.'.join(map(str, pyversion))
            ))


def find_description(docs):
    """
    Determine the package description from DESCRIPTION

    :Parameters:
      `docs` : ``dict``
        Docs config section

    :Return: Tuple of summary, description and license
             (``('summary', 'description', 'license')``)
             (all may be ``None``)
    :Rtype: ``tuple``
    """
    summary = None
    filename = docs.get('meta.summary', 'SUMMARY').strip()
    if filename and _os.path.isfile(filename):
        fp = open(filename)
        try:
            try:
                summary = fp.read().strip().splitlines()[0].rstrip()
            except IndexError:
                summary = ''
        finally:
            fp.close()

    description = None
    filename = docs.get('meta.description', 'DESCRIPTION').strip()
    if filename and _os.path.isfile(filename):
        fp = open(filename)
        try:
            description = fp.read().rstrip()
        finally:
            fp.close()

        if summary is None and description:
            from docutils import core
            summary = core.publish_parts(
                source=description,
                source_path=filename,
                writer_name='html',
            )['title'].encode('utf-8')

    return summary, description


def find_classifiers(docs):
    """
    Determine classifiers from CLASSIFIERS

    :return: List of classifiers (``['classifier', ...]``)
    :rtype: ``list``
    """
    filename = docs.get('meta.classifiers', 'CLASSIFIERS').strip()
    if filename and _os.path.isfile(filename):
        fp = open(filename)
        try:
            content = fp.read()
        finally:
            fp.close()
        content = [item.strip() for item in content.splitlines()]
        return [item for item in content if item and not item.startswith('#')]
    return []


def find_provides(docs):
    """
    Determine provides from PROVIDES

    :return: List of provides (``['provides', ...]``)
    :rtype: ``list``
    """
    filename = docs.get('meta.provides', 'PROVIDES').strip()
    if filename and _os.path.isfile(filename):
        fp = open(filename)
        try:
            content = fp.read()
        finally:
            fp.close()
        content = [item.strip() for item in content.splitlines()]
        return [item for item in content if item and not item.startswith('#')]
    return []


def find_license(docs):
    """
    Determine license from LICENSE

    :return: License text
    :rtype: ``str``
    """
    filename = docs.get('meta.license', 'LICENSE').strip()
    if filename and _os.path.isfile(filename):
        fp = open(filename)
        try:
            return fp.read().rstrip()
        finally:
            fp.close()
    return None


def find_packages(manifest):
    """ Determine packages and subpackages """
    packages = {}
    collect = manifest.get('packages.collect', '').split()
    lib = manifest.get('packages.lib', '.')
    try:
        sep = _os.path.sep
    except AttributeError:
        sep = _os.path.join('1', '2')[1:-1]
    for root in collect:
        for dirpath, _, filenames in _shell.walk(_os.path.join(lib, root)):
            if dirpath.find('.svn') >= 0 or dirpath.find('.git') >= 0:
                continue
            if '__init__.py' in filenames:
                packages[
                    _os.path.normpath(dirpath).replace(sep, '.')
                ] = None
    packages = packages.keys()
    packages.sort()
    return packages


def find_data(name, docs):
    """ Determine data files """
    result = []
    if docs.get('extra', '').strip():
        result.append(_data.Documentation(docs['extra'].split(),
            prefix='share/doc/%s' % name,
        ))
    if docs.get('examples.dir', '').strip():
        tpl = ['recursive-include %s *' % docs['examples.dir']]
        if docs.get('examples.ignore', '').strip():
            tpl.extend(["global-exclude %s" % item
                for item in docs['examples.ignore'].split()
            ])
        strip = int(docs.get('examples.strip', '') or 0)
        result.append(_data.Documentation.from_templates(*tpl, **{
            'strip': strip,
            'prefix': 'share/doc/%s' % name,
            'preserve': 1,
        }))
    if docs.get('userdoc.dir', '').strip():
        tpl = ['recursive-include %s *' % docs['userdoc.dir']]
        if docs.get('userdoc.ignore', '').strip():
            tpl.extend(["global-exclude %s" % item
                for item in docs['userdoc.ignore'].split()
            ])
        strip = int(docs.get('userdoc.strip', '') or 0)
        result.append(_data.Documentation.from_templates(*tpl, **{
            'strip': strip,
            'prefix': 'share/doc/%s' % name,
            'preserve': 1,
        }))
    if docs.get('apidoc.dir', '').strip():
        tpl = ['recursive-include %s *' % docs['apidoc.dir']]
        if docs.get('apidoc.ignore', '').strip():
            tpl.extend(["global-exclude %s" % item
                for item in docs['apidoc.ignore'].split()
            ])
        strip = int(docs.get('apidoc.strip', '') or 0)
        result.append(_data.Documentation.from_templates(*tpl, **{
            'strip': strip,
            'prefix': 'share/doc/%s' % name,
            'preserve': 1,
        }))
    if docs.get('man', '').strip():
        result.extend(_data.Manpages.dispatch(docs['man'].split()))
    return result


def make_manifest(manifest, config, docs, kwargs):
    """ Create file list to pack up """
    # pylint: disable = R0912
    kwargs = kwargs.copy()
    kwargs['script_args'] = ['install']
    kwargs['packages'] = list(kwargs.get('packages') or ()) + [
        '_setup', '_setup.py2', '_setup.py3',
    ] + list(manifest.get('packages.extra', '').split() or ())
    _core._setup_stop_after = "commandline"
    try:
        dist = _core.setup(**kwargs)
    finally:
        _core._setup_stop_after = None

    result = ['MANIFEST', 'PKG-INFO', 'setup.py'] + list(config)
    # TODO: work with default values:
    for key in ('classifiers', 'description', 'summary', 'provides',
                'license'):
        filename = docs.get('meta.' + key, '').strip()
        if filename and _os.path.isfile(filename):
            result.append(filename)

    cmd = dist.get_command_obj("build_py")
    cmd.ensure_finalized()
    #from pprint import pprint; pprint(("build_py", cmd.get_source_files()))
    for item in cmd.get_source_files():
        result.append(_posixpath.sep.join(
            _os.path.normpath(item).split(_os.path.sep)
        ))

    cmd = dist.get_command_obj("build_ext")
    cmd.ensure_finalized()
    #from pprint import pprint; pprint(("build_ext", cmd.get_source_files()))
    for item in cmd.get_source_files():
        result.append(_posixpath.sep.join(
            _os.path.normpath(item).split(_os.path.sep)
        ))
    for ext in cmd.extensions:
        if ext.depends:
            result.extend([_posixpath.sep.join(
                _os.path.normpath(item).split(_os.path.sep)
            ) for item in ext.depends])

    cmd = dist.get_command_obj("build_clib")
    cmd.ensure_finalized()
    if cmd.libraries:
        #import pprint; pprint.pprint(("build_clib", cmd.get_source_files()))
        for item in cmd.get_source_files():
            result.append(_posixpath.sep.join(
                _os.path.normpath(item).split(_os.path.sep)
            ))
        for lib in cmd.libraries:
            if lib[1].get('depends'):
                result.extend([_posixpath.sep.join(
                    _os.path.normpath(item).split(_os.path.sep)
                ) for item in lib[1]['depends']])

    cmd = dist.get_command_obj("build_scripts")
    cmd.ensure_finalized()
    #import pprint; pprint.pprint(("build_scripts", cmd.get_source_files()))
    if cmd.get_source_files():
        for item in cmd.get_source_files():
            result.append(_posixpath.sep.join(
                _os.path.normpath(item).split(_os.path.sep)
            ))

    cmd = dist.get_command_obj("install_data")
    cmd.ensure_finalized()
    #from pprint import pprint; pprint(("install_data", cmd.get_inputs()))
    try:
        strings = basestring
    except NameError:
        strings = (str, unicode)

    for item in cmd.get_inputs():
        if isinstance(item, strings):
            result.append(item)
        else:
            result.extend(item[1])

    for item in manifest.get('dist', '').split():
        result.append(item)
        if _os.path.isdir(item):
            for filename in _shell.files(item):
                result.append(filename)

    result = dict([(item, None) for item in result]).keys()
    result.sort()
    return result


def run(config=('package.cfg',), ext=None, script_args=None, manifest_only=0):
    """ Main runner """
    if ext is None:
        ext = []

    cfg = _util.SafeConfigParser()
    cfg.read(config)
    pkg = dict(cfg.items('package'))
    python_min = pkg.get('python.min') or None
    python_max = pkg.get('python.max') or None
    check_python_version('python', python_min, python_max)
    pypy_min = pkg.get('pypy.min') or None
    pypy_max = pkg.get('pypy.max') or None
    check_python_version('pypy', pypy_min, pypy_max)
    jython_min = pkg.get('jython.min') or None
    jython_max = pkg.get('jython.max') or None
    check_python_version('jython', jython_min, jython_max)

    manifest = dict(cfg.items('manifest'))
    try:
        docs = dict(cfg.items('docs'))
    except _config_parser.NoSectionError:
        docs = {}

    summary, description = find_description(docs)
    scripts = manifest.get('scripts', '').strip() or None
    if scripts:
        scripts = scripts.split()
    modules = manifest.get('modules', '').strip() or None
    if modules:
        modules = modules.split()
    keywords = docs.get('meta.keywords', '').strip() or None
    if keywords:
        keywords = keywords.split()
    revision = pkg.get('version.revision', '').strip()
    if revision:
        revision = "-r%s" % (revision,)

    kwargs = {
        'name': pkg['name'],
        'version': "%s%s" % (
            pkg['version.number'],
            ["", "-dev%s" % (revision,)][_util.humanbool(
                'version.dev', pkg.get('version.dev', 'false')
            )],
        ),
        'provides': find_provides(docs),
        'description': summary,
        'long_description': description,
        'classifiers': find_classifiers(docs),
        'keywords': keywords,
        'author': pkg['author.name'],
        'author_email': pkg['author.email'],
        'maintainer': pkg.get('maintainer.name'),
        'maintainer_email': pkg.get('maintainer.email'),
        'url': pkg.get('url.homepage'),
        'download_url': pkg.get('url.download'),
        'license': find_license(docs),
        'package_dir': {'': manifest.get('packages.lib', '.')},
        'packages': find_packages(manifest),
        'py_modules': modules,
        'ext_modules': ext,
        'scripts': scripts,
        'script_args': script_args,
        'data_files': find_data(pkg['name'], docs),
        'cmdclass': {
            'build'       : _commands.Build,
            'build_ext'   : _commands.BuildExt,
            'install'     : _commands.Install,
            'install_data': _commands.InstallData,
            'install_lib' : _commands.InstallLib,
        }
    }
    for key in ('provides',):
        if key not in _core.setup_keywords:
            del kwargs[key]

    if manifest_only:
        return make_manifest(manifest, config, docs, kwargs)

    # monkey-patch crappy manifest writer away.
    from distutils.command import sdist
    sdist.sdist.get_file_list = sdist.sdist.read_manifest

    return _core.setup(**kwargs)
