#! /usr/bin/env python2.7
#
# Copyright (c) 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.
#
# 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: Andreas Sandberg

import os
import sys

from style.file_types import lang_type
import style.verifiers
from style.region import all_regions

from style.style import StdioUI
from style import repo

verifier_names = dict([
    (c.__name__, c) for c in style.verifiers.all_verifiers ])

def verify(filename, regions=all_regions, verbose=False, verifiers=None,
           auto_fix=False):
    ui = StdioUI()
    opts = {
        "fix_all" : auto_fix,
    }
    base = os.path.join(os.path.dirname(__file__), "..")
    if verifiers is None:
        verifiers = style.verifiers.all_verifiers

    if verbose:
        print "Verifying %s[%s]..." % (filename, regions)
    for verifier in [ v(ui, opts, base=base) for v in verifiers ]:
        if verbose:
            print "Applying %s (%s)" % (
                verifier.test_name, verifier.__class__.__name__)
        if verifier.apply(filename, regions=regions):
            return False
    return True

def detect_repo():
    repo_classes = repo.detect_repo()
    if not repo_classes:
        print >> sys.stderr, "Error: Failed to detect repository type, no " \
            "known repository type found."
        sys.exit(1)
    elif len(repo_classes) > 1:
        print >> sys.stderr, "Error: Detected multiple repository types."
        sys.exit(1)
    else:
        return repo_classes[0]()

repo_types = {
    "auto" : detect_repo,
    "none" : lambda : None,
    "git" : repo.GitRepo,
    "hg" : repo.MercurialRepo,
}

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(
        description="Check a file for gem5 style violations",
        epilog="""If no files are specified, the style checker tries to
        determine the list of modified and added files from the version
        control system and checks those."""
    )

    parser.add_argument("--verbose", "-v", action="count",
                        help="Produce verbose output")

    parser.add_argument("--fix", "-f", action="store_true",
                        help="Automatically fix style violations.")

    parser.add_argument("--modifications", "-m", action="store_true",
                        help="""Apply the style checker to modified regions
                        instead of whole files""")

    parser.add_argument("--repo-type", choices=repo_types, default="auto",
                        help="Repository type to use to detect changes")

    parser.add_argument("--checker", "-c", choices=verifier_names, default=[],
                        action="append",
                        help="""Style checkers to run. Can be specified
                        multiple times.""")

    parser.add_argument("files", metavar="FILE", nargs="*",
                        type=str,
                        help="Source file(s) to inspect")

    args = parser.parse_args()

    repo = repo_types[args.repo_type]()

    verifiers = [ verifier_names[name] for name in args.checker ] \
                if args.checker else None

    files = args.files
    if not files and repo:
        added, modified = repo.staged_files()
        files = [ repo.file_path(f) for f in added + modified ]

    for filename in files:
        if args.modifications and repo and repo.in_repo(filename):
            regions = repo.modified_regions(filename)
        else:
            regions = all_regions

        if not verify(filename, regions=regions,
                      verbose=args.verbose,
                      verifiers=verifiers,
                      auto_fix=args.fix):
            sys.exit(1)
