# Copyright 2022 The Pigweed Authors
#
# Licensed 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
#
#     https://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.
"""Checks a Pigweed module's format and structure."""

import argparse
import logging
import pathlib
import glob
from enum import Enum
from typing import Callable, NamedTuple, Sequence

_LOG = logging.getLogger(__name__)

CheckerFunction = Callable[[str], None]


def check_modules(modules: Sequence[str]) -> int:
    if len(modules) > 1:
        _LOG.info('Checking %d modules', len(modules))

    passed = 0

    for path in modules:
        if len(modules) > 1:
            print()
            print(f' {path} '.center(80, '='))

        passed += check_module(path)

    if len(modules) > 1:
        _LOG.info('%d of %d modules passed', passed, len(modules))

    return 0 if passed == len(modules) else 1


def check_module(module) -> bool:
    """Runs module checks on one module; returns True if the module passes."""

    if not pathlib.Path(module).is_dir():
        _LOG.error('No directory found: %s', module)
        return False

    found_any_warnings = False
    found_any_errors = False

    _LOG.info('Checking module: %s', module)
    # Run each checker.
    for check in _checkers:
        _LOG.debug(
            'Running checker: %s - %s',
            check.name,
            check.description,
        )
        issues = list(check.run(module))

        # Log any issues found
        for issue in issues:
            if issue.severity == Severity.ERROR:
                log_level = logging.ERROR
                found_any_errors = True
            elif issue.severity == Severity.WARNING:
                log_level = logging.WARNING
                found_any_warnings = True

            # Try to make an error message that will help editors open the part
            # of the module in question (e.g. vim's 'cerr' functionality).
            components = [
                x for x in (
                    issue.file,
                    issue.line_number,
                    issue.line_contents,
                ) if x
            ]
            editor_error_line = ':'.join(components)
            if editor_error_line:
                _LOG.log(log_level, '%s', check.name)
                print(editor_error_line, issue.message)
            else:
                # No per-file error to put in a "cerr" list, so just log.
                _LOG.log(log_level, '%s: %s', check.name, issue.message)

        if issues:
            _LOG.debug('Done running checker: %s (issues found)', check.name)
        else:
            _LOG.debug('Done running checker: %s (OK)', check.name)

    # TODO(keir): Give this a proper ASCII art treatment.
    if not found_any_warnings and not found_any_errors:
        _LOG.info('OK: Module %s looks good; no errors or warnings found',
                  module)
    if found_any_errors:
        _LOG.error('FAIL: Found errors when checking module %s', module)
        return False

    return True


class Checker(NamedTuple):
    name: str
    description: str
    run: CheckerFunction


class Severity(Enum):
    ERROR = 1
    WARNING = 2


class Issue(NamedTuple):
    message: str
    file: str = ''
    line_number: str = ''
    line_contents: str = ''
    severity: Severity = Severity.ERROR


_checkers = []


def checker(pwck_id, description):
    def inner_decorator(function):
        _checkers.append(Checker(pwck_id, description, function))
        return function

    return inner_decorator


@checker('PWCK001', 'If there is Python code, there is a setup.py')
def check_python_proper_module(directory):
    module_python_files = glob.glob(f'{directory}/**/*.py', recursive=True)
    module_setup_py = glob.glob(f'{directory}/**/setup.py', recursive=True)
    if module_python_files and not module_setup_py:
        yield Issue('Python code present but no setup.py.')


@checker('PWCK002', 'If there are C++ files, there are C++ tests')
def check_have_cc_tests(directory):
    module_cc_files = glob.glob(f'{directory}/**/*.cc', recursive=True)
    module_cc_test_files = glob.glob(f'{directory}/**/*test.cc',
                                     recursive=True)
    if module_cc_files and not module_cc_test_files:
        yield Issue('C++ code present but no tests at all (you monster).')


@checker('PWCK003', 'If there are Python files, there are Python tests')
def check_have_python_tests(directory):
    module_py_files = glob.glob(f'{directory}/**/*.py', recursive=True)
    module_py_test_files = glob.glob(f'{directory}/**/*test*.py',
                                     recursive=True)
    if module_py_files and not module_py_test_files:
        yield Issue('Python code present but no tests (you monster).')


@checker('PWCK004', 'There is a README.md')
def check_has_readme(directory):
    if not glob.glob(f'{directory}/README.md'):
        yield Issue('Missing module top-level README.md')


@checker('PWCK005', 'There is ReST documentation (*.rst)')
def check_has_rst_docs(directory):
    if not glob.glob(f'{directory}/**/*.rst', recursive=True):
        yield Issue(
            'Missing ReST documentation; need at least e.g. "docs.rst"')


@checker('PWCK006', 'If C++, have <mod>/public/<mod>/*.h or '
         '<mod>/public_override/*.h')
def check_has_public_or_override_headers(directory):
    # TODO: Should likely have a decorator to check for C++ in a checker, or
    # other more useful and cachable mechanisms.
    if (not glob.glob(f'{directory}/**/*.cc', recursive=True)
            and not glob.glob(f'{directory}/**/*.h', recursive=True)):
        # No C++ files.
        return

    module_name = pathlib.Path(directory).name

    has_public_cpp_headers = glob.glob(f'{directory}/public/{module_name}/*.h')
    has_public_cpp_override_headers = glob.glob(
        f'{directory}/public_overrides/**/*.h')

    if not has_public_cpp_headers and not has_public_cpp_override_headers:
        yield Issue(f'Have C++ code but no public/{module_name}/*.h '
                    'found and no public_overrides/ found')

    multiple_public_directories = glob.glob(f'{directory}/public/*')
    if len(multiple_public_directories) != 1:
        yield Issue(f'Have multiple directories under public/; there should '
                    f'only be a single directory: "public/{module_name}". '
                    'Perhaps you were looking for public_overrides/?.')


def register_subcommand(parser: argparse.ArgumentParser) -> None:
    """Check that a module matches Pigweed's module guidelines."""
    parser.add_argument('modules', nargs='+', help='The module to check')
    parser.set_defaults(func=check_modules)
