# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
r"""
Class describing simulation results
"""

import collections
import re

from Testplan import Result

_REGEX_REMOVE = [
    # Remove UVM time.
    re.compile(r'@\s+[\d.]+\s+[np]s: '),
    re.compile(r'\[[\d.]+\s+[np]s\] '),
    # Remove assertion time.
    re.compile(r'\(time [\d.]+ [PF]S\) '),
    # Remove leading spaces.
    re.compile(r'^\s+'),
    # Remove extra white spaces.
    re.compile(r'\s+(?=\s)'),
]

_REGEX_STRIP = [
    # Strip TB instance name.
    re.compile(r'[\w_]*top\.\S+\.(\w+)'),
    # Strip assertion.
    re.compile(r'(?<=Assertion )\S+\.(\w+)'),
]

# Regular expression for a separator: EOL or some of punctuation marks.
_SEPARATOR_RE = '($|[ ,.:;])'

_REGEX_STAR = [
    # Replace hex numbers with 0x (needs to be called before other numbers).
    re.compile(r'0x\s*[\da-fA-F]+'),
    # Replace hex numbers with 'h (needs to be called before other numbers).
    re.compile(r'\'h\s*[\da-fA-F]+'),
    # Floating point numbers at the beginning of a word, example "10.1ns".
    # (needs to be called before other numbers).
    re.compile(r'(?<=[^a-zA-Z0-9])\d+\.\d+'),
    # Replace all isolated numbers. Isolated numbers are numbers surrounded by
    # special symbols, for example ':' or '+' or '_', excluding parenthesis.
    # So a number with a letter or a round bracket on any one side, is
    # considered non-isolated number and is not starred by these expressions.
    re.compile(r'(?<=[^a-zA-Z0-9\(\)])\d+(?=($|[^a-zA-Z0-9\(\)]))'),
    # Replace numbers surrounded by parenthesis after a space and followed by a
    # separator.
    re.compile(r'(?<= \()\s*\d+\s*(?=\)%s)' % _SEPARATOR_RE),
    # Replace hex/decimal numbers after an equal sign or a semicolon and
    # followed by a separator. Uses look-behind pattern which need a
    # fixed width, thus the apparent redundancy.
    re.compile(r'(?<=[\w\]][=:])[\da-fA-F]+(?=%s)' % _SEPARATOR_RE),
    re.compile(r'(?<=[\w\]][=:] )[\da-fA-F]+(?=%s)' % _SEPARATOR_RE),
    re.compile(r'(?<=[\w\]] [=:])[\da-fA-F]+(?=%s)' % _SEPARATOR_RE),
    re.compile(r'(?<=[\w\]] [=:] )[\da-fA-F]+(?=%s)' % _SEPARATOR_RE),
    # Replace decimal number at the beginning of the word.
    re.compile(r'(?<= )\d+(?=\S)'),
    # Remove decimal number at end of the word and before '=' or '[' or
    # ',' or '.' or '('.
    re.compile(r'(?<=\S)\d+(?=($|[ =\[,\.\(]))'),
    # Replace the instance string.
    re.compile(r'(?<=instance)\s*=\s*\S+'),
]


class SimResults:
    '''An object wrapping up a table of results for some tests

    self.table is a list of Result objects, each of which
    corresponds to one or more runs of the test with a given name.

    self.buckets contains a dictionary accessed by the failure signature,
    holding all failing tests with the same signature.
    '''

    def __init__(self, items, results):
        self.table = []
        self.buckets = collections.defaultdict(list)
        self._name_to_row = {}
        for item in items:
            self._add_item(item, results)

    def _add_item(self, item, results):
        '''Recursively add a single item to the table of results'''
        status = results[item]
        if status in ["F", "K"]:
            bucket = self._bucketize(item.launcher.fail_msg.message)
            self.buckets[bucket].append(
                (item, item.launcher.fail_msg.line_number,
                 item.launcher.fail_msg.context))

        # Runs get added to the table directly
        if item.target == "run":
            self._add_run(item, status)

    def _add_run(self, item, status):
        '''Add an entry to table for item'''
        row = self._name_to_row.get(item.name)
        if row is None:
            row = Result(item.name,
                         job_runtime=item.job_runtime,
                         simulated_time=item.simulated_time)
            self.table.append(row)
            self._name_to_row[item.name] = row

        else:
            # Record the max job_runtime of all reseeds.
            if item.job_runtime > row.job_runtime:
                row.job_runtime = item.job_runtime
                row.simulated_time = item.simulated_time

        if status == 'P':
            row.passing += 1
        row.total += 1

    def _bucketize(self, fail_msg):
        bucket = fail_msg
        # Remove stuff.
        for regex in _REGEX_REMOVE:
            bucket = regex.sub('', bucket)
        # Strip stuff.
        for regex in _REGEX_STRIP:
            bucket = regex.sub(r'\g<1>', bucket)
        # Replace with '*'.
        for regex in _REGEX_STAR:
            bucket = regex.sub('*', bucket)
        return bucket
