from distutils import log
import distutils.command.sdist as orig
import os
import sys
import io
import contextlib

from setuptools.extern import six, ordered_set

from .py36compat import sdist_add_defaults

import pkg_resources

_default_revctrl = list


def walk_revctrl(dirname=''):
    """Find all files under revision control"""
    for ep in pkg_resources.iter_entry_points('setuptools.file_finders'):
        for item in ep.load()(dirname):
            yield item


class sdist(sdist_add_defaults, orig.sdist):
    """Smart sdist that finds anything supported by revision control"""

    user_options = [
        ('formats=', None,
         "formats for source distribution (comma-separated list)"),
        ('keep-temp', 'k',
         "keep the distribution tree around after creating " +
         "archive file(s)"),
        ('dist-dir=', 'd',
         "directory to put the source distribution archive(s) in "
         "[default: dist]"),
    ]

    negative_opt = {}

    README_EXTENSIONS = ['', '.rst', '.txt', '.md']
    READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS)

    def run(self):
        self.run_command('egg_info')
        ei_cmd = self.get_finalized_command('egg_info')
        self.filelist = ei_cmd.filelist
        self.filelist.append(os.path.join(ei_cmd.egg_info, 'SOURCES.txt'))
        self.check_readme()

        # Run sub commands
        for cmd_name in self.get_sub_commands():
            self.run_command(cmd_name)

        self.make_distribution()

        dist_files = getattr(self.distribution, 'dist_files', [])
        for file in self.archive_files:
            data = ('sdist', '', file)
            if data not in dist_files:
                dist_files.append(data)

    def initialize_options(self):
        orig.sdist.initialize_options(self)

        self._default_to_gztar()

    def _default_to_gztar(self):
        # only needed on Python prior to 3.6.
        if sys.version_info >= (3, 6, 0, 'beta', 1):
            return
        self.formats = ['gztar']

    def make_distribution(self):
        """
        Workaround for #516
        """
        with self._remove_os_link():
            orig.sdist.make_distribution(self)

    @staticmethod
    @contextlib.contextmanager
    def _remove_os_link():
        """
        In a context, remove and restore os.link if it exists
        """

        class NoValue:
            pass

        orig_val = getattr(os, 'link', NoValue)
        try:
            del os.link
        except Exception:
            pass
        try:
            yield
        finally:
            if orig_val is not NoValue:
                setattr(os, 'link', orig_val)

    def __read_template_hack(self):
        # This grody hack closes the template file (MANIFEST.in) if an
        #  exception occurs during read_template.
        # Doing so prevents an error when easy_install attempts to delete the
        #  file.
        try:
            orig.sdist.read_template(self)
        except Exception:
            _, _, tb = sys.exc_info()
            tb.tb_next.tb_frame.f_locals['template'].close()
            raise

    # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle
    #  has been fixed, so only override the method if we're using an earlier
    #  Python.
    has_leaky_handle = (
        sys.version_info < (2, 7, 2)
        or (3, 0) <= sys.version_info < (3, 1, 4)
        or (3, 2) <= sys.version_info < (3, 2, 1)
    )
    if has_leaky_handle:
        read_template = __read_template_hack

    def _add_defaults_optional(self):
        if six.PY2:
            sdist_add_defaults._add_defaults_optional(self)
        else:
            super()._add_defaults_optional()
        if os.path.isfile('pyproject.toml'):
            self.filelist.append('pyproject.toml')

    def _add_defaults_python(self):
        """getting python files"""
        if self.distribution.has_pure_modules():
            build_py = self.get_finalized_command('build_py')
            self.filelist.extend(build_py.get_source_files())
            self._add_data_files(self._safe_data_files(build_py))

    def _safe_data_files(self, build_py):
        """
        Extracting data_files from build_py is known to cause
        infinite recursion errors when `include_package_data`
        is enabled, so suppress it in that case.
        """
        if self.distribution.include_package_data:
            return ()
        return build_py.data_files

    def _add_data_files(self, data_files):
        """
        Add data files as found in build_py.data_files.
        """
        self.filelist.extend(
            os.path.join(src_dir, name)
            for _, src_dir, _, filenames in data_files
            for name in filenames
        )

    def _add_defaults_data_files(self):
        try:
            if six.PY2:
                sdist_add_defaults._add_defaults_data_files(self)
            else:
                super()._add_defaults_data_files()
        except TypeError:
            log.warn("data_files contains unexpected objects")

    def check_readme(self):
        for f in self.READMES:
            if os.path.exists(f):
                return
        else:
            self.warn(
                "standard file not found: should have one of " +
                ', '.join(self.READMES)
            )

    def make_release_tree(self, base_dir, files):
        orig.sdist.make_release_tree(self, base_dir, files)

        # Save any egg_info command line options used to create this sdist
        dest = os.path.join(base_dir, 'setup.cfg')
        if hasattr(os, 'link') and os.path.exists(dest):
            # unlink and re-copy, since it might be hard-linked, and
            # we don't want to change the source version
            os.unlink(dest)
            self.copy_file('setup.cfg', dest)

        self.get_finalized_command('egg_info').save_version_info(dest)

    def _manifest_is_not_generated(self):
        # check for special comment used in 2.7.1 and higher
        if not os.path.isfile(self.manifest):
            return False

        with io.open(self.manifest, 'rb') as fp:
            first_line = fp.readline()
        return (first_line !=
                '# file GENERATED by distutils, do NOT edit\n'.encode())

    def read_manifest(self):
        """Read the manifest file (named by 'self.manifest') and use it to
        fill in 'self.filelist', the list of files to include in the source
        distribution.
        """
        log.info("reading manifest file '%s'", self.manifest)
        manifest = open(self.manifest, 'rb')
        for line in manifest:
            # The manifest must contain UTF-8. See #303.
            if not six.PY2:
                try:
                    line = line.decode('UTF-8')
                except UnicodeDecodeError:
                    log.warn("%r not UTF-8 decodable -- skipping" % line)
                    continue
            # ignore comments and blank lines
            line = line.strip()
            if line.startswith('#') or not line:
                continue
            self.filelist.append(line)
        manifest.close()

    def check_license(self):
        """Checks if license_file' or 'license_files' is configured and adds any
        valid paths to 'self.filelist'.
        """

        files = ordered_set.OrderedSet()

        opts = self.distribution.get_option_dict('metadata')

        # ignore the source of the value
        _, license_file = opts.get('license_file', (None, None))

        if license_file is None:
            log.debug("'license_file' option was not specified")
        else:
            files.add(license_file)

        try:
            files.update(self.distribution.metadata.license_files)
        except TypeError:
            log.warn("warning: 'license_files' option is malformed")

        for f in files:
            if not os.path.exists(f):
                log.warn(
                    "warning: Failed to find the configured license file '%s'",
                    f)
                files.remove(f)

        self.filelist.extend(files)
