#!/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('could not open file {}: {}'.format(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(">>%s<<\n" % s_line[:-1])
                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\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

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) ]
