# Copyright (C) 2012 Google, Inc.
# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""this module is responsible for finding python tests."""

import logging
import re

try:
    from importlib.util import source_from_cache
except ImportError:  # Python 2
    def source_from_cache(path):
        return path[:-1]


_log = logging.getLogger(__name__)


class _DirectoryTree(object):
    def __init__(self, filesystem, top_directory, starting_subdirectory):
        self.filesystem = filesystem
        self.top_directory = filesystem.realpath(top_directory)
        self.search_directory = self.top_directory
        self.top_package = ''
        if starting_subdirectory:
            self.top_package = starting_subdirectory.replace(filesystem.sep, '.') + '.'
            self.search_directory = filesystem.join(self.top_directory, starting_subdirectory)

    def find_modules(self, suffixes, sub_directory=None):
        if sub_directory:
            search_directory = self.filesystem.join(self.top_directory, sub_directory)
        else:
            search_directory = self.search_directory

        def file_filter(filesystem, dirname, basename):
            return any(basename.endswith(suffix) for suffix in suffixes)

        filenames = self.filesystem.files_under(search_directory, file_filter=file_filter)
        return [self.to_module(filename) for filename in filenames]

    def to_module(self, path):
        return path.replace(self.top_directory + self.filesystem.sep, '').replace(self.filesystem.sep, '.')[:-3]

    def subpath(self, path):
        """Returns the relative path from the top of the tree to the path, or None if the path is not under the top of the tree."""
        realpath = self.filesystem.realpath(self.filesystem.join(self.top_directory, path))
        if realpath.startswith(self.top_directory + self.filesystem.sep):
            return realpath.replace(self.top_directory + self.filesystem.sep, '')
        return None

    def clean(self):
        """Delete all .pyc files in the tree that have no matching .py file."""
        _log.debug("Cleaning orphaned *.pyc files from: %s" % self.search_directory)
        filenames = self.filesystem.files_under(self.search_directory)
        for filename in filenames:
            if filename.endswith(".pyc"):
                try:
                    orphan = source_from_cache(filename) not in filenames
                except ValueError:
                    orphan = True
                if orphan:
                    _log.info("Deleting orphan *.pyc file: %s" % filename)
                    self.filesystem.remove(filename)


class Finder(object):
    def __init__(self, filesystem):
        self.filesystem = filesystem
        self.trees = []
        self._names_to_skip = []

    def add_tree(self, top_directory, starting_subdirectory=None):
        self.trees.append(_DirectoryTree(self.filesystem, top_directory, starting_subdirectory))

    def skip(self, names, reason, bugid):
        self._names_to_skip.append(tuple([names, reason, bugid]))

    def additional_paths(self, paths):
        return [tree.top_directory for tree in self.trees if tree.top_directory not in paths]

    def clean_trees(self):
        for tree in self.trees:
            tree.clean()

    def is_module(self, name):
        relpath = name.replace('.', self.filesystem.sep) + '.py'
        return any(self.filesystem.exists(self.filesystem.join(tree.top_directory, relpath)) for tree in self.trees)

    def is_dotted_name(self, name):
        return re.match(r'[a-zA-Z.][a-zA-Z0-9_.]*', name)

    def to_module(self, path):
        for tree in self.trees:
            if path.startswith(tree.top_directory):
                return tree.to_module(path)
        return None

    def find_names(self, args, find_all):
        suffixes = ['_unittest.py', '_integrationtest.py']
        if args:
            names = []
            for arg in args:
                names.extend(self._find_names_for_arg(arg, suffixes))
            return names

        return self._default_names(suffixes, find_all)

    def _find_names_for_arg(self, arg, suffixes):
        realpath = self.filesystem.realpath(arg)
        if self.filesystem.exists(realpath):
            names = self._find_in_trees(realpath, suffixes)
            if not names:
                _log.error("%s is not in one of the test trees." % arg)
            return names

        # See if it's a python package in a tree (or a relative path from the top of a tree).
        names = self._find_in_trees(arg.replace('.', self.filesystem.sep), suffixes)
        if names:
            return names

        if self.is_dotted_name(arg):
            # The name may not exist, but that's okay; we'll find out later.
            return [arg]

        _log.error("%s is not a python name or an existing file or directory." % arg)
        return []

    def _find_in_trees(self, path, suffixes):
        for tree in self.trees:
            relpath = tree.subpath(path)
            if not relpath:
                continue
            if self.filesystem.isfile(path):
                return [tree.to_module(path)]
            else:
                return tree.find_modules(suffixes, path)
        return []

    def _default_names(self, suffixes, find_all):
        modules = []
        for tree in self.trees:
            modules.extend(tree.find_modules(suffixes))
        modules.sort()

        for module in modules:
            _log.debug("Found: %s" % module)

        if not find_all:
            for (names, reason, bugid) in self._names_to_skip:
                self._exclude(modules, names, reason, bugid)

        return modules

    def _exclude(self, modules, module_prefixes, reason, bugid):
        _log.info('Skipping tests in the following modules or packages because they %s:' % reason)
        for prefix in module_prefixes:
            _log.info('    %s' % prefix)
            modules_to_exclude = list(filter(lambda m: m.startswith(prefix), modules))
            for m in modules_to_exclude:
                if len(modules_to_exclude) > 1:
                    _log.debug('        %s' % m)
                modules.remove(m)
        _log.info('    (https://bugs.webkit.org/show_bug.cgi?id=%d; use --all to include)' % bugid)
        _log.info('')
