#!/usr/bin/env python3
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

from __future__ import print_function
import lintutils
from subprocess import PIPE, STDOUT
import argparse
import multiprocessing as mp
import sys
import platform
from functools import partial


# NOTE(wesm):
#
# * readability/casting is disabled as it aggressively warns about functions
#   with names like "int32", so "int32(x)", where int32 is a function name,
#   warns with
_filters = '''
-whitespace/comments
-readability/casting
-readability/todo
-readability/alt_tokens
-build/header_guard
-build/c++11
-build/include_what_you_use
-runtime/references
-build/include_order
'''.split()


def _get_chunk_key(filenames):
    # lists are not hashable so key on the first filename in a chunk
    return filenames[0]


def _check_some_files(completed_processes, filenames):
    # cpplint outputs complaints in '/path:line_number: complaint' format,
    # so we can scan its output to get a list of files to fix
    result = completed_processes[_get_chunk_key(filenames)]
    return lintutils.stdout_pathcolonline(result, filenames)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Runs cpplint on all of the source files.")
    parser.add_argument("--cpplint_binary",
                        required=True,
                        help="Path to the cpplint binary")
    parser.add_argument("--exclude_globs",
                        help="Filename containing globs for files "
                        "that should be excluded from the checks")
    parser.add_argument("--source_dir",
                        required=True,
                        action="append",
                        help="Root directory of the source code")
    parser.add_argument("--quiet", default=False,
                        action="store_true",
                        help="If specified, only print errors")
    arguments = parser.parse_args()

    exclude_globs = []
    if arguments.exclude_globs:
        with open(arguments.exclude_globs) as f:
            exclude_globs.extend(line.strip() for line in f)

    linted_filenames = []
    for source_dir in arguments.source_dir:
        for path in lintutils.get_sources(source_dir, exclude_globs):
            linted_filenames.append(str(path))

    cmd = [
        arguments.cpplint_binary,
        '--verbose=2',
        '--linelength=90',
        '--filter=' + ','.join(_filters)
    ]
    if (arguments.cpplint_binary.endswith('.py') and
            platform.system() == 'Windows'):
        # Windows doesn't support executable scripts; execute with
        # sys.executable
        cmd.insert(0, sys.executable)
    if arguments.quiet:
        cmd.append('--quiet')
    else:
        print("\n".join(map(lambda x: "Linting {}".format(x),
                            linted_filenames)))

    # lint files in chunks: each invocation of cpplint will process 16 files
    chunks = lintutils.chunk(linted_filenames, 16)
    cmds = [cmd + some for some in chunks]
    results = lintutils.run_parallel(cmds, stdout=PIPE, stderr=STDOUT)

    error = False
    # record completed processes (keyed by the first filename in the input
    # chunk) for lookup in _check_some_files
    completed_processes = {
        _get_chunk_key(filenames): result
        for filenames, result in zip(chunks, results)
    }
    checker = partial(_check_some_files, completed_processes)
    pool = mp.Pool()
    try:
        # scan the outputs of various cpplint invocations in parallel to
        # distill a list of problematic files
        for problem_files, stdout in pool.imap(checker, chunks):
            if problem_files:
                if isinstance(stdout, bytes):
                    stdout = stdout.decode('utf8')
                print(stdout, file=sys.stderr)
                error = True
    except Exception:
        error = True
        raise
    finally:
        pool.terminate()
        pool.join()

    sys.exit(1 if error else 0)
