# Copyright 2014 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from collections import defaultdict
import fnmatch
import json
import os
import re
import subprocess
import sys

_REPO_ROOT = os.path.abspath(os.path.dirname(__file__))


# TODO(dcheng): It's kind of horrible that this is copy and pasted from
# presubmit_canned_checks.py, but it's far easier than any of the alternatives.
def _ReportErrorFileAndLine(filename, line_num, dummy_line):
    """Default error formatter for _FindNewViolationsOfRule."""
    return '%s:%s' % (filename, line_num)


class MockCannedChecks(object):

    def _FindNewViolationsOfRule(self,
                                 callable_rule,
                                 input_api,
                                 source_file_filter=None,
                                 error_formatter=_ReportErrorFileAndLine):
        """Find all newly introduced violations of a per-line rule (a callable).

    Arguments:
      callable_rule: a callable taking a file extension and line of input and
        returning True if the rule is satisfied and False if there was a
        problem.
      input_api: object to enumerate the affected files.
      source_file_filter: a filter to be passed to the input api.
      error_formatter: a callable taking (filename, line_number, line) and
        returning a formatted error string.

    Returns:
      A list of the newly-introduced violations reported by the rule.
    """
        errors = []
        for f in input_api.AffectedFiles(include_deletes=False,
                                         file_filter=source_file_filter):
            # For speed, we do two passes, checking first the full file.
            # Shelling out to the SCM to determine the changed region can be
            # quite expensive on Win32. Assuming that most files will be kept
            # problem-free, we can skip the SCM operations most of the time.
            extension = str(f.UnixLocalPath()).rsplit('.', 1)[-1]
            if all(callable_rule(extension, line) for line in f.NewContents()):
                # No violation found in full text: can skip considering diff.
                continue

            for line_num, line in f.ChangedContents():
                if not callable_rule(extension, line):
                    errors.append(
                        error_formatter(f.LocalPath(), line_num, line))

        return errors


class MockInputApi(object):
    """Mock class for the InputApi class.

  This class can be used for unittests for presubmit by initializing the files
  attribute as the list of changed files.
  """

    DEFAULT_FILES_TO_SKIP = ()

    def __init__(self):
        self.basename = os.path.basename
        self.canned_checks = MockCannedChecks()
        self.fnmatch = fnmatch
        self.json = json
        self.re = re

        # We want os_path.exists() and os_path.isfile() to work for files
        # that are both in the filesystem and mock files we have added
        # via InitFiles().
        # By setting os_path to a copy of os.path rather than directly we
        # can not only have os_path.exists() be a combined output for fake
        # files and real files in the filesystem.
        import importlib.util
        SPEC_OS_PATH = importlib.util.find_spec('os.path')
        os_path1 = importlib.util.module_from_spec(SPEC_OS_PATH)
        SPEC_OS_PATH.loader.exec_module(os_path1)
        sys.modules['os_path1'] = os_path1
        self.os_path = os_path1

        self.platform = sys.platform
        self.python_executable = sys.executable
        self.python3_executable = sys.executable
        self.platform = sys.platform
        self.subprocess = subprocess
        self.sys = sys
        self.files = []
        self.is_committing = False
        self.change = MockChange([])
        self.presubmit_local_path = os.path.dirname(
            os.path.abspath(sys.argv[0]))
        self.is_windows = sys.platform == 'win32'
        self.no_diffs = False
        # Although this makes assumptions about command line arguments used by
        # test scripts that create mocks, it is a convenient way to set up the
        # verbosity via the input api.
        self.verbose = '--verbose' in sys.argv

    def InitFiles(self, files):
        # Actual presubmit calls normpath, but too many tests break to do this
        # right in MockFile().
        for f in files:
            f._local_path = os.path.normpath(f._local_path)
        self.files = files
        files_that_exist = {
            p.AbsoluteLocalPath()
            for p in files if p.Action() != 'D'
        }

        def mock_exists(path):
            if not os.path.isabs(path):
                path = os.path.join(self.presubmit_local_path, path)
            path = os.path.normpath(path)
            return path in files_that_exist or any(
                f.startswith(path)
                for f in files_that_exist) or os.path.exists(path)

        def mock_isfile(path):
            if not os.path.isabs(path):
                path = os.path.join(self.presubmit_local_path, path)
            path = os.path.normpath(path)
            return path in files_that_exist or os.path.isfile(path)

        def mock_glob(pattern, *args, **kwargs):
            return fnmatch.filter(files_that_exist, pattern)

        # Do not stub these in the constructor to not break existing tests.
        self.os_path.exists = mock_exists
        self.os_path.isfile = mock_isfile
        self.glob = mock_glob

    def AffectedFiles(self, file_filter=None, include_deletes=True):
        for file in self.files:
            if file_filter and not file_filter(file):
                continue
            if not include_deletes and file.Action() == 'D':
                continue
            yield file

    def RightHandSideLines(self, source_file_filter=None):
        affected_files = self.AffectedSourceFiles(source_file_filter)
        for af in affected_files:
            lines = af.ChangedContents()
            for line in lines:
                yield (af, line[0], line[1])

    def AffectedSourceFiles(self, file_filter=None):
        return self.AffectedFiles(file_filter=file_filter,
                                  include_deletes=False)

    def AffectedTestableFiles(self, file_filter=None):
        return self.AffectedFiles(file_filter=file_filter,
                                  include_deletes=False)

    def FilterSourceFile(self, file, files_to_check=(), files_to_skip=()):
        local_path = file.UnixLocalPath()
        found_in_files_to_check = not files_to_check
        if files_to_check:
            if type(files_to_check) is str:
                raise TypeError(
                    'files_to_check should be an iterable of strings')
            for pattern in files_to_check:
                compiled_pattern = re.compile(pattern)
                if compiled_pattern.match(local_path):
                    found_in_files_to_check = True
                    break
        if files_to_skip:
            if type(files_to_skip) is str:
                raise TypeError(
                    'files_to_skip should be an iterable of strings')
            for pattern in files_to_skip:
                compiled_pattern = re.compile(pattern)
                if compiled_pattern.match(local_path):
                    return False
        return found_in_files_to_check

    def LocalPaths(self):
        return [file.LocalPath() for file in self.files]

    def PresubmitLocalPath(self):
        return self.presubmit_local_path

    def ReadFile(self, filename, mode='r'):
        if hasattr(filename, 'AbsoluteLocalPath'):
            filename = filename.AbsoluteLocalPath()
        norm_filename = os.path.normpath(filename)
        for file_ in self.files:
            to_check = (file_.LocalPath(), file_.AbsoluteLocalPath())
            if filename in to_check or norm_filename in to_check:
                return '\n'.join(file_.NewContents())
        # Otherwise, file is not in our mock API.
        raise IOError("No such file or directory: '%s'" % filename)


class MockOutputApi(object):
    """Mock class for the OutputApi class.

  An instance of this class can be passed to presubmit unittests for outputting
  various types of results.
  """

    class PresubmitResult(object):

        def __init__(self, message, items=None, long_text='', locations=[]):
            self.message = message
            self.items = items
            self.long_text = long_text
            self.locations = locations

        def __repr__(self):
            return self.message

    class PresubmitError(PresubmitResult):

        def __init__(self, *args, **kwargs):
            MockOutputApi.PresubmitResult.__init__(self, *args, **kwargs)
            self.type = 'error'

    class PresubmitPromptWarning(PresubmitResult):

        def __init__(self, *args, **kwargs):
            MockOutputApi.PresubmitResult.__init__(self, *args, **kwargs)
            self.type = 'warning'

    class PresubmitNotifyResult(PresubmitResult):

        def __init__(self, *args, **kwargs):
            MockOutputApi.PresubmitResult.__init__(self, *args, **kwargs)
            self.type = 'notify'

    class PresubmitPromptOrNotify(PresubmitResult):

        def __init__(self, *args, **kwargs):
            MockOutputApi.PresubmitResult.__init__(self, *args, **kwargs)
            self.type = 'promptOrNotify'

    class PresubmitResultLocation(object):

        def __init__(self, file_path, start_line, end_line):
            self.file_path = file_path
            self.start_line = start_line
            self.end_line = end_line

    def __init__(self):
        self.more_cc = []

    def AppendCC(self, more_cc):
        self.more_cc.append(more_cc)


class MockFile(object):
    """Mock class for the File class.

  This class can be used to form the mock list of changed files in
  MockInputApi for presubmit unittests.
  """

    def __init__(self,
                 local_path,
                 new_contents,
                 old_contents=None,
                 action='A',
                 scm_diff=None):
        self._local_path = local_path
        self._new_contents = new_contents
        self._changed_contents = [(i + 1, l)
                                  for i, l in enumerate(new_contents)]
        self._action = action
        if scm_diff:
            self._scm_diff = scm_diff
        else:
            self._scm_diff = ("--- /dev/null\n+++ %s\n@@ -0,0 +1,%d @@\n" %
                              (local_path, len(new_contents)))
            for l in new_contents:
                self._scm_diff += "+%s\n" % l
        self._old_contents = old_contents or []

    def __str__(self):
        return self._local_path

    def Action(self):
        return self._action

    def ChangedContents(self):
        return self._changed_contents

    def NewContents(self):
        return self._new_contents

    def LocalPath(self):
        return self._local_path

    def AbsoluteLocalPath(self):
        return os.path.join(_REPO_ROOT, self._local_path)

    # This method must be functionally identical to
    # AffectedFile.UnixLocalPath(), but must normalize Windows-style
    # paths even on non-Windows platforms because tests contain them
    def UnixLocalPath(self):
        return self._local_path.replace('\\', '/')

    def GenerateScmDiff(self):
        return self._scm_diff

    def OldContents(self):
        return self._old_contents

    def Extension(self):
        _, ext = os.path.splitext(self._local_path)
        return ext

    def rfind(self, p):
        """Required when os.path.basename() is called on MockFile."""
        return self._local_path.rfind(p)

    def __getitem__(self, i):
        """Required when os.path.basename() is called on MockFile."""
        return self._local_path[i]

    def __len__(self):
        """Required when os.path.basename() is called on MockFile."""
        return len(self._local_path)

    def replace(self, altsep, sep):
        """Required when os.path.basename() is called on MockFile."""
        return self._local_path.replace(altsep, sep)


class MockAffectedFile(MockFile):
    pass


class MockChange(object):
    """Mock class for Change class.

  This class can be used in presubmit unittests to mock the query of the
  current change.
  """

    def __init__(self, changed_files):
        self._changed_files = changed_files
        self.author_email = None
        self.footers = defaultdict(list)

    def LocalPaths(self):
        return self._changed_files

    def AffectedFiles(self,
                      include_dirs=False,
                      include_deletes=True,
                      file_filter=None):
        return self._changed_files

    def GitFootersFromDescription(self):
        return self.footers

    def RepositoryRoot(self):
        return _REPO_ROOT
