#!/usr/bin/env python
# -*- mode: python -*-
# -*- coding: utf-8 -*-

# 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
#
#     https://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.

"""
Provide the code necessary for packaging and installing avro-python3.

The avro-python3 software is designed for Python 3, but this file and the packaging software supports Python 2.7.

https://pypi.org/project/avro-python3/
"""

import distutils.command.clean
import distutils.dir_util
import distutils.errors
import distutils.file_util
import distutils.log
import fnmatch
import glob
import os
import subprocess

import setuptools

import pycodestyle

_HERE = os.path.dirname(os.path.abspath(__file__))
_AVRO_DIR = os.path.join(_HERE, 'avro')
_VERSION_FILE_NAME = 'VERSION.txt'

def _is_distribution():
    """Tests whether setup.py is invoked from a distribution.

    Returns:
        True if setup.py runs from a distribution.
        False otherwise, ie. if setup.py runs from a version control work tree.
    """
    # If a file PKG-INFO exists as a sibling of setup.py,
    # assume we are running as source distribution:
    return os.path.exists(os.path.join(_HERE, 'PKG-INFO'))


def _generate_package_data():
    """Generate package data.

    This data will already exist in a distribution package,
    so this function only runs for local version control work tree.
    """
    distutils.log.info('Generating package data')

    # Avro top-level source directory:
    root_dir = os.path.dirname(os.path.dirname(_HERE))

    # Create a PEP440 compliant version file.
    version_file_path = os.path.join(root_dir, 'share', _VERSION_FILE_NAME)
    with open(version_file_path) as vin:
        version = vin.read().replace('-', '+')
    with open(os.path.join(_AVRO_DIR, _VERSION_FILE_NAME), 'w') as vout:
        vout.write(version)

    # Copy necessary avsc files:
    avsc_files = (
        (('schemas', 'org', 'apache', 'avro', 'ipc', 'HandshakeRequest.avsc'), ''),
        (('schemas', 'org', 'apache', 'avro', 'ipc', 'HandshakeResponse.avsc'), ''),
        (('test', 'schemas', 'interop.avsc'), ('tests',)),
    )

    for src, dst in avsc_files:
        src = os.path.join(root_dir, 'share', *src)
        dst = os.path.join(_AVRO_DIR, *dst)
        distutils.file_util.copy_file(src, dst)


class CleanCommand(distutils.command.clean.clean):
    """A command to clean up install artifacts and replaceable, generated files."""

    def _replaceable(self):
        """Get the list of files to delete."""
        for name in ('dist', 'avro_python3.egg-info', os.path.join(_AVRO_DIR, _VERSION_FILE_NAME)):
            if os.path.exists(name):
                yield name
        for root, dirnames, filenames in os.walk(_AVRO_DIR):
            if '__pycache__' in dirnames:
                dirnames.remove('__pycache__')
                yield os.path.join(root, '__pycache__')
            for name in fnmatch.filter(filenames, '*.avsc'):
                yield os.path.join(root, name)

    def run(self):
        super().run()
        for name in self._replaceable():
            if self.dry_run:
                distutils.log.info('Would remove %s', name)
            elif os.path.isdir(name):
                # distutils logs this for us
                distutils.dir_util.remove_tree(name)
            else:
                distutils.log.info('Removing %s', name)
                os.remove(name)


class GenerateInteropDataCommand(setuptools.Command):
    """A command to generate Avro files for data interop test."""

    user_options = [
      ('schema-file=', None, 'path to input Avro schema file'),
      ('output-path=', None, 'path to output Avro data files'),
    ]

    def initialize_options(self):
        self.schema_file = os.path.join(os.getcwd(), 'interop.avsc')
        self.output_path = os.getcwd()

    def finalize_options(self):
        pass

    def run(self):
        from avro.tests import gen_interop_data
        gen_interop_data.generate(self.schema_file, self.output_path)


class LintCommand(setuptools.Command):
    """Run pycodestyle on all your modules"""
    description = __doc__
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        # setuptools does not seem to make pycodestyle available
        # in the pythonpath, so we do it ourselves.
        try:
            env = {'PYTHONPATH': next(glob.iglob('.eggs/pycodestyle-*.egg'))}
        except StopIteration:
            env = None  # pycodestyle is already installed
        try:
            subprocess.run(['python3', '-m', 'pycodestyle', '.'], env=env)
        except subprocess.CalledProcessError:
            raise distutils.errors.DistutilsError("pycodestyle exited with a nonzero exit code.")


def main():
    if not _is_distribution():
        _generate_package_data()

    setuptools.setup(cmdclass={
        "clean": CleanCommand,
        "generate_interop_data": GenerateInteropDataCommand,
        "lint": LintCommand,
    })


if __name__ == '__main__':
    main()
