#!/usr/bin/env python
#
# Search a given log file for patterns defined in patterns.py and produce a
# HTML snippet for the matching lines.
#
# Ideas for improvements:
# - Group together similar issues. A good rule would be by description
#   so if a warning/error happens for several source files in the project
#   we would only list it as a single issue. Should extend the description
#   with the count (i.e. "warning: bla blup [20 times]")
#   Could merge the first 2 or 3 instances to show in the details section.
# - Write highlighted html log with all matches highlighted/linked?
from cgi import escape
from collections import deque
from patterns import default_search
import os.path
import re
import sys


_JENKINS_POOL_PATTERN = r'\[.*]\s'
_JENKINS_POOL_REGEX = re.compile('^'+_JENKINS_POOL_PATTERN)


class _Matcher(object):
    '''Matching engine. Keeps data structures to match a single line against
    a fixed list of patterns.'''
    def __init__(self, patterns):
        # Create a combined master regex combining all patterns.
        combined = ''
        merge = ''
        for pattern in patterns:
            # Convert named groups into anonymous ones to avoid name clashes.
            p = pattern.pattern
            p = re.sub(r'\(\?P<[^>]+>', '(?:', p)
            combined += merge
            combined += '(?:%s)' % p
            merge = '|'
        self.combined_regex = re.compile(combined)
        self.patterns = patterns

    def match_line(self, line):
        if line[0] == '[':
            line = _JENKINS_POOL_REGEX.sub("", line, 1)
        if not self.combined_regex.match(line):
            return None
        for pattern in default_search:
            m = pattern.regex.search(line)
            if m:
                return (pattern, m.groupdict())
        return None


class _Match(object):
    '''Used for the results of a match.'''


def _match_with_context(matcher, istream, lines_before, lines_after):
    prev_lines = deque()
    needs_lines = deque()
    for line in istream:
        if len(needs_lines) > 0:
            for match in needs_lines:
                match.after.append(line)
            match = needs_lines[0]
            if len(match.after) == lines_after:
                needs_lines.popleft()
                yield match

        m = matcher.match_line(line)
        if m is not None:
            pattern, matches = m
            match = _Match()
            match.line = line
            match.pattern = pattern
            match.matches = matches
            match.before = list(prev_lines)
            match.after = []
            needs_lines.append(match)

        prev_lines.append(line)
        if len(prev_lines) > lines_before:
            prev_lines.popleft()

    for match in needs_lines:
        yield match


def _match_summary(match):
    template = match.pattern.html_template
    sub = {}
    sub.update(match.pattern.__dict__)
    sub.update(match.matches)
    if 'file_name' in sub:
        sub['file_name'] = os.path.basename(sub['file_name'])
    return escape(template.format(**sub))


def _sort_by_severity(matches):
    return sorted(matches, key=lambda m: m.pattern.severity)


def _make_html_snippets(matches, limit):
    def _prepare_lines(lines):
        string = escape(''.join(lines))
        if len(string) > 0 and string[-1] == '\n':
            string = string[:-1]
        return string

    matches = list(matches)
    if len(matches) == 0:
        return False

    sys.stdout.write('<div style="margin-bottom: 2em;">Found %d issues:</div>\n' % (len(matches), ))

    limited = False
    if len(matches) > limit:
        # Sort by severity so we cut the less severe ones.
        matches = _sort_by_severity(matches)
        matches = matches[:limit]
        limited = True

    for match in matches:
        match.summary = _match_summary(match)
        match.before = _prepare_lines(match.before)
        match.after = _prepare_lines(match.after)
        match.line = _prepare_lines(match.line)
        sys.stdout.write('''\
<details class="match">
    <summary><b>{summary}</b></summary>
    <pre style="margin-bottom: 1.5em;">
{before}
<span style='color: red'>{line}</span>
{after}</pre>
</details>'''.format(**match.__dict__))

    if limited:
        sys.stdout.write('<b>... (limited to first %d issues)</b>\n' % limit)

    return True


if __name__ == '__main__':
    lines_before = 5
    lines_after = 2
    matcher = _Matcher(default_search)
    matches = _match_with_context(matcher, sys.stdin,
                                  lines_before=lines_before,
                                  lines_after=lines_after)
    limit = 12 # Limit the amount of issues we show.
    had_issues = _make_html_snippets(matches, limit)
    if had_issues:
        sys.exit(1)
