#!/usr/bin/env python3
#
# Copyright (c) 2014, 2016 ARM Limited
# All rights reserved
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2006 The Regents of The University of Michigan
# Copyright (c) 2007,2011 The Hewlett-Packard Development Company
# Copyright (c) 2016 Advanced Micro Devices, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# 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;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
# OWNER OR 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.

from abc import ABCMeta, abstractmethod
from difflib import SequenceMatcher
import inspect
import os
import re
import sys

from . import style
from . import sort_includes
from .region import *
from .file_types import lang_type


def safefix(fix_func):
    """Decorator for the fix functions of the Verifier class.
    This function wraps the fix function and creates a backup file
    just in case there is an error.
    """

    def safefix_wrapper(*args, **kwargs):
        # Check to be sure that this is decorating a function we expect:
        # a class method with filename as the first argument (after self)
        assert os.path.exists(args[1])
        self = args[0]
        assert is_verifier(self.__class__)
        filename = args[1]

        # Now, Let's make a backup file.
        from shutil import copyfile

        backup_name = filename + ".bak"
        copyfile(filename, backup_name)

        # Try to apply the fix. If it fails, then we revert the file
        # Either way, we need to clean up our backup file
        try:
            fix_func(*args, **kwargs)
        except Exception as e:
            # Restore the original file to the backup file
            self.ui.write("Error! Restoring the original file.\n")
            copyfile(backup_name, filename)
            raise
        finally:
            # Clean up the backup file
            os.remove(backup_name)

    return safefix_wrapper


def _modified_regions(old, new):
    try:
        m = SequenceMatcher(a=old, b=new, autojunk=False)
    except TypeError:
        # autojunk was introduced in Python 2.7. We need a fallback
        # mechanism to support old Python versions.
        m = SequenceMatcher(a=old, b=new)
    regions = Regions()
    for tag, i1, i2, j1, j2 in m.get_opcodes():
        if tag != "equal":
            regions.extend(Region(i1, i2))
    return regions


class Verifier(object, metaclass=ABCMeta):
    """Base class for style verifiers

    Verifiers check for style violations and optionally fix such
    violations. Implementations should either inherit from this class
    (Verifier) if they need to work on entire files or LineVerifier if
    they operate on a line-by-line basis.

    Subclasses must define these class attributes:
      languages = set of strings identifying applicable languages
      test_name = long descriptive name of test, will be used in
                  messages such as "error in <foo>" or "invalid <foo>"
      opt_name = short name used to generate command-line options to
                 control the test (--fix-<foo>, --ignore-<foo>, etc.)

    """

    def __init__(self, ui, opts, base=None):
        self.ui = ui
        self.base = base

        # opt_name must be defined as a class attribute of derived classes.
        # Check test-specific opts first as these have precedence.
        self.opt_fix = opts.get("fix_" + self.opt_name, False)
        self.opt_ignore = opts.get("ignore_" + self.opt_name, False)
        self.opt_skip = opts.get("skip_" + self.opt_name, False)
        # If no test-specific opts were set, then set based on "-all" opts.
        if not (self.opt_fix or self.opt_ignore or self.opt_skip):
            self.opt_fix = opts.get("fix_all", False)
            self.opt_ignore = opts.get("ignore_all", False)
            self.opt_skip = opts.get("skip_all", False)

    def normalize_filename(self, name):
        abs_name = os.path.abspath(name)
        if self.base is None:
            return abs_name

        abs_base = os.path.abspath(self.base)
        return os.path.relpath(abs_name, start=abs_base)

    def open(self, filename, mode):
        try:
            f = open(filename, mode)
        except OSError as msg:
            print(f"could not open file {filename}: {msg}")
            return None

        return f

    def skip(self, filename):
        # We never want to handle symlinks, so always skip them: If the
        # location pointed to is a directory, skip it. If the location is a
        # file inside the gem5 directory, it will be checked as a file, so
        # symlink can be skipped. If the location is a file outside gem5, we
        # don't want to check it anyway.
        if os.path.islink(filename):
            return True
        return lang_type(filename) not in self.languages

    def apply(self, filename, regions=all_regions):
        """Possibly apply to specified regions of file 'filename'.

        Verifier is skipped if --skip-<test> option was provided or if
        file is not of an applicable type.  Otherwise file is checked
        and error messages printed.  Errors are fixed or ignored if
        the corresponding --fix-<test> or --ignore-<test> options were
        provided.  If neither, the user is prompted for an action.

        Returns True to abort, False otherwise.
        """
        if not (self.opt_skip or self.skip(filename)):
            errors = self.check(filename, regions)
            if errors and not self.opt_ignore:
                if self.opt_fix:
                    self.fix(filename, regions)
                else:
                    result = self.ui.prompt(
                        "(a)bort, (i)gnore, or (f)ix?", "aif", "a"
                    )
                    if result == "f":
                        self.fix(filename, regions)
                    elif result == "a":
                        return True  # abort

        return False

    @abstractmethod
    def check(self, filename, regions=all_regions, fobj=None, silent=False):
        """Check specified regions of file 'filename'.

        Given that it is possible that the current contents of the file
        differ from the file as 'staged to commit', for those cases, and
        maybe others, the argument fobj should be a file object open and reset
        with the contents matching what the file would look like after the
        commit. This is needed keep the messages using 'filename' meaningful.

        The argument silent is useful to prevent output when we run check in
        the staged file vs the actual file to detect if the user forgot
        staging fixes to the commit. This way, we prevent reporting errors
        twice in stderr.

        Line-by-line checks can simply provide a check_line() method
        that returns True if the line is OK and False if it has an
        error.  Verifiers that need a multi-line view (like
        SortedIncludes) must override this entire function.

        Returns a count of errors (0 if none), though actual non-zero
        count value is not currently used anywhere.
        """
        pass

    @abstractmethod
    def fix(self, filename, regions=all_regions):
        """Fix specified regions of file 'filename'.

        Line-by-line fixes can simply provide a fix_line() method that
        returns the fixed line. Verifiers that need a multi-line view
        (like SortedIncludes) must override this entire function.
        """
        pass


class LineVerifier(Verifier):
    def check(self, filename, regions=all_regions, fobj=None, silent=False):
        close = False
        if fobj is None:
            fobj = self.open(filename, "rb")
            close = True

        lang = lang_type(filename)
        assert lang in self.languages

        errors = 0
        for num, line in enumerate(fobj):
            if num not in regions:
                continue
            s_line = line.decode("utf-8").rstrip("\n")
            if not self.check_line(s_line, language=lang):
                if not silent:
                    self.ui.write(
                        "invalid %s in %s:%d\n"
                        % (self.test_name, filename, num + 1)
                    )
                    if self.ui.verbose:
                        self.ui.write(f">>{s_line[:-1]}<<\n")
                errors += 1
        if close:
            fobj.close()
        return errors

    @safefix
    def fix(self, filename, regions=all_regions):
        f = self.open(filename, "r+")

        lang = lang_type(filename)
        assert lang in self.languages

        lines = list(f)

        f.seek(0)
        f.truncate()

        for i, line in enumerate(lines):
            line = line.rstrip("\n")
            if i in regions:
                line = self.fix_line(line, language=lang)

            f.write(line)
            f.write("\n")
        f.close()
        self.current_language = None

    @abstractmethod
    def check_line(self, line, **kwargs):
        pass

    @abstractmethod
    def fix_line(self, line, **kwargs):
        pass


class Whitespace(LineVerifier):
    """Check whitespace.

    Specifically:
    - No tabs used for indent
    - No trailing whitespace
    """

    languages = set(
        ("C", "C++", "swig", "python", "asm", "isa", "scons", "make", "dts")
    )
    trail_only = set(("make", "dts"))

    test_name = "whitespace"
    opt_name = "white"

    _lead = re.compile(r"^([ \t]+)")
    _trail = re.compile(r"([ \t]+)$")

    def skip_lead(self, language):
        return language in Whitespace.trail_only

    def check_line(self, line, language):
        if not self.skip_lead(language):
            match = Whitespace._lead.search(line)
            if match and match.group(1).find("\t") != -1:
                return False

        match = Whitespace._trail.search(line)
        if match:
            return False

        return True

    def fix_line(self, line, language):
        if not self.skip_lead(language) and Whitespace._lead.search(line):
            newline = ""
            for i, c in enumerate(line):
                if c == " ":
                    newline += " "
                elif c == "\t":
                    newline += " " * (
                        style.tabsize - len(newline) % style.tabsize
                    )
                else:
                    newline += line[i:]
                    break

            line = newline

        return line.rstrip()


class SortedIncludes(Verifier):
    """Check for proper sorting of include statements"""

    languages = sort_includes.default_languages
    test_name = "include file order"
    opt_name = "include"

    def __init__(self, *args, **kwargs):
        super(SortedIncludes, self).__init__(*args, **kwargs)
        self.sort_includes = sort_includes.SortIncludes()

    def check(self, filename, regions=all_regions, fobj=None, silent=False):
        close = False
        if fobj is None:
            fobj = self.open(filename, "rb")
            close = True
        norm_fname = self.normalize_filename(filename)

        old = [l.decode("utf-8").rstrip("\n") for l in fobj]
        if close:
            fobj.close()

        if len(old) == 0:
            return 0

        language = lang_type(filename, old[0])
        new = list(self.sort_includes(old, norm_fname, language))

        modified = _modified_regions(old, new) & regions

        if modified:
            if not silent:
                self.ui.write(
                    "invalid sorting of includes in %s. Note: If "
                    "there is more than one empty line under the "
                    "#include region, please reduce it to one.\n" % (filename)
                )
                if self.ui.verbose:
                    for start, end in modified.regions:
                        self.ui.write("bad region [%d, %d)\n" % (start, end))
            return 1

        return 0

    @safefix
    def fix(self, filename, regions=all_regions):
        f = self.open(filename, "r+")
        norm_fname = self.normalize_filename(filename)

        old = f.readlines()
        lines = [l.rstrip("\n") for l in old]
        language = lang_type(filename, lines[0])
        sort_lines = list(self.sort_includes(lines, norm_fname, language))
        new = "".join(line + "\n" for line in sort_lines)

        f.seek(0)
        f.truncate()

        for i, line in enumerate(sort_lines):
            f.write(line)
            f.write("\n")
        f.close()


class ControlSpace(LineVerifier):
    """Check for exactly one space after if/while/for"""

    languages = set(("C", "C++"))
    test_name = "spacing after if/while/for"
    opt_name = "control"

    _any_control = re.compile(r"\b(if|while|for)([ \t]*)\(")

    def check_line(self, line, **kwargs):
        match = ControlSpace._any_control.search(line)
        return not (match and match.group(2) != " ")

    def fix_line(self, line, **kwargs):
        new_line = ControlSpace._any_control.sub(r"\1 (", line)
        return new_line


class LineLength(LineVerifier):
    languages = set(("C", "C++", "swig", "python", "asm", "isa", "scons"))
    test_name = "line length"
    opt_name = "length"

    def check_line(self, line, **kwargs):
        return style.normalized_len(line) <= 79

    def fix(self, filename, regions=all_regions, **kwargs):
        self.ui.write("Warning: cannot automatically fix overly long lines.\n")

    def fix_line(self, line):
        pass


class ControlCharacters(LineVerifier):
    languages = set(("C", "C++", "swig", "python", "asm", "isa", "scons"))
    test_name = "control character"
    opt_name = "ascii"

    invalid = "".join(
        [chr(i) for i in range(0, 0x20) if chr(i) not in ("\n", "\t")]
    )

    def check_line(self, line, **kwargs):
        return self.fix_line(line) == line

    def fix_line(self, line, **kwargs):
        return "".join(c for c in line if c not in ControlCharacters.invalid)


class BoolCompare(LineVerifier):
    languages = set(("C", "C++", "python"))
    test_name = "boolean comparison"
    opt_name = "boolcomp"

    regex = re.compile(r"\s*==\s*([Tt]rue|[Ff]alse)\b")

    def check_line(self, line, **kwargs):
        return self.regex.search(line) == None

    def fix_line(self, line, **kwargs):
        match = self.regex.search(line)
        if match:
            if match.group(1) in ("true", "True"):
                line = self.regex.sub("", line)
            else:
                self.ui.write(
                    "Warning: cannot automatically fix "
                    "comparisons with false/False.\n"
                )
        return line


class StructureBraces(LineVerifier):
    """Check if the opening braces of structures are not on the same line of
    the structure name. This includes classes, structs, enums and unions.

    This verifier matches lines starting in optional indent, followed by
    an optional typedef and the structure's keyword, followed by any
    character until the first opening brace is seen. Any extra characters
    after the opening brace are saved for a recursive check, if needed.

    This fixes, for example:
        1) "struct A {"
        2) "enum{"
        3) "    class B { // This is a class"
        4) "union { struct C {"
    to:
        1) "struct A\n{"
        2) "enum\n{"
        3) "    class B\n    {\n        // This is a class"
        4) "union\n{\n        struct C\n        {"

    @todo Make this work for multi-line structure declarations. e.g.,

        class MultiLineClass
          : public BaseClass {
    """

    languages = set(("C", "C++"))
    test_name = "structure opening brace position"
    opt_name = "structurebrace"

    # Matches the indentation of the line
    regex_indentation = "(?P<indentation>\s*)"
    # Matches an optional "typedef" before the keyword
    regex_typedef = "(?P<typedef>(typedef\s+)?)"
    # Matches the structure's keyword
    regex_keyword = "(?P<keyword>class|struct|enum|union)"
    # A negative lookahead to avoid incorrect matches with variable's names
    # e.g., "classifications = {" should not be fixed here.
    regex_avoid = "(?![^\{\s])"
    # Matches anything after the keyword and before the opening brace.
    # e.g., structure name, base type, type of inheritance, etc
    regex_name = "(?P<name>[^\{]*)"
    # Matches anything after the opening brace, which should be
    # parsed recursively
    regex_extra = "(?P<extra>.*)$"
    regex = re.compile(
        r"^"
        + regex_indentation
        + regex_typedef
        + regex_keyword
        + regex_avoid
        + regex_name
        + "\{"
        + regex_extra
    )

    def check_line(self, line, **kwargs):
        return (self.regex.search(line) == None) or (
            line.count("{") == line.count("};")
        )

    def fix_line(self, line, **kwargs):
        match = self.regex.search(line)

        if match:
            # Move the opening brace to the next line
            match_indentation = match.group("indentation")
            match_typedef = match.group("typedef")
            match_keyword = match.group("keyword")
            match_name = match.group("name").rstrip()
            match_extra = match.group("extra").lstrip()
            line = (
                match_indentation
                + match_typedef
                + match_keyword
                + match_name
                + "\n"
                + match_indentation
                + "{"
            )

            # The opening brace should be alone in its own line, so move any
            # extra contents to the next line
            if match_extra != "":
                # Check if the extra line obeys the opening brace rule
                # (in case there are nested declarations)
                line_extra = match_indentation + "    " + match_extra
                if not self.check_line(line_extra):
                    line_extra = self.fix_line(line_extra)
                line += "\n" + line_extra

        return line


def is_verifier(cls):
    """Determine if a class is a Verifier that can be instantiated"""

    return (
        inspect.isclass(cls)
        and issubclass(cls, Verifier)
        and not inspect.isabstract(cls)
    )


# list of all verifier classes
all_verifiers = [
    v for n, v in inspect.getmembers(sys.modules[__name__], is_verifier)
]
