#!/usr/bin/env python2
#
# 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.
#
# Authors: Nathan Binkert
#          Steve Reinhardt
#          Andreas Sandberg

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

import style
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):
    """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.)

    """

    __metaclass__ = ABCMeta

    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 = file(filename, mode)
        except OSError, msg:
            print 'could not open file %s: %s' % (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, 'r')
            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
            line = line.rstrip('\n')
            if not self.check_line(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" % 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, 'r')
            close = True
        norm_fname = self.normalize_filename(filename)

        old = [ l.rstrip('\n') for l in fobj.xreadlines() ]
        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+')

        old = f.readlines()
        lines = [ l.rstrip('\n') for l in old ]
        language = lang_type(filename, lines[0])
        sort_lines = list(self.sort_includes(lines, filename, 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'

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

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

    def fix_line(self, line, **kwargs):
        return line.translate(None, 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) ]
