# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt

"""Reporter foundation for coverage.py."""
import sys

from coverage import env
from coverage.files import prep_patterns, FnmatchMatcher
from coverage.misc import CoverageException, NoSource, NotPython, ensure_dir_for_file, file_be_gone


def render_report(output_path, reporter, morfs):
    """Run a report generator, managing the output file.

    This function ensures the output file is ready to be written to. Then writes
    the report to it. Then closes the file and cleans up.

    """
    file_to_close = None
    delete_file = False

    if output_path == "-":
        outfile = sys.stdout
    else:
        # Ensure that the output directory is created; done here
        # because this report pre-opens the output file.
        # HTMLReport does this using the Report plumbing because
        # its task is more complex, being multiple files.
        ensure_dir_for_file(output_path)
        open_kwargs = {}
        if env.PY3:
            open_kwargs["encoding"] = "utf8"
        outfile = open(output_path, "w", **open_kwargs)
        file_to_close = outfile

    try:
        return reporter.report(morfs, outfile=outfile)
    except CoverageException:
        delete_file = True
        raise
    finally:
        if file_to_close:
            file_to_close.close()
            if delete_file:
                file_be_gone(output_path)           # pragma: part covered (doesn't return)


def get_analysis_to_report(coverage, morfs):
    """Get the files to report on.

    For each morf in `morfs`, if it should be reported on (based on the omit
    and include configuration options), yield a pair, the `FileReporter` and
    `Analysis` for the morf.

    """
    file_reporters = coverage._get_file_reporters(morfs)
    config = coverage.config

    if config.report_include:
        matcher = FnmatchMatcher(prep_patterns(config.report_include), "report_include")
        file_reporters = [fr for fr in file_reporters if matcher.match(fr.filename)]

    if config.report_omit:
        matcher = FnmatchMatcher(prep_patterns(config.report_omit), "report_omit")
        file_reporters = [fr for fr in file_reporters if not matcher.match(fr.filename)]

    if not file_reporters:
        raise CoverageException("No data to report.")

    for fr in sorted(file_reporters):
        try:
            analysis = coverage._analyze(fr)
        except NoSource:
            if not config.ignore_errors:
                raise
        except NotPython:
            # Only report errors for .py files, and only if we didn't
            # explicitly suppress those errors.
            # NotPython is only raised by PythonFileReporter, which has a
            # should_be_python() method.
            if fr.should_be_python():
                if config.ignore_errors:
                    msg = "Couldn't parse Python file '{}'".format(fr.filename)
                    coverage._warn(msg, slug="couldnt-parse")
                else:
                    raise
        else:
            yield (fr, analysis)
