"""@ingroup vigilance
@file
Contains data structures to normalize the representation of code quality metrics independent of the tool used to generate them.
"""
from abc import ABCMeta, abstractproperty
from collections import namedtuple

_satisfaction = namedtuple('_satisfaction', ['satisfied', 'message'])

class Satisfaction(_satisfaction):
    """The result of a constraint validation.
    """
    def __new__(cls, satisfied, message=None):
        return super(Satisfaction, cls).__new__(cls, satisfied, message)

class QualityItem(object):
    """Represents a single item from a code quality report.
    """
    __metaclass__ = ABCMeta
    def __init__(self, metrics):
        self._metrics = metrics

    @property
    def metrics(self):
        """Returns the quality metrics for the QualityItem.
        """
        return self._metrics

    @abstractproperty
    def identifier(self):
        """Returns a string identifier for the item under test.
        This is used to provide friendlier error messages to end users.
        """
        pass

class QualityReport(object):
    """Represents a parsed code quality report.
    Constraints are applied to coverage reports to determine if a code base meets the required standards.
    """
    def __init__(self, items):
        """Creates a new QualityReport instance.
        @param items A list of QualityItem instances that together comprise the full coverage report.
        """
        self.items = items

    def scrutinize(self, constraints):
        """Vigilantly asserts that the provided constraints are satisfied by the quality report.
        @param constraints A vigilance.constraints.ConstraintSet instance.
        @returns A list containing any failed vigilance.representation.Satisfaction instances generated by the constraint application.
        """
        dissatifactions = []
        for item in self.items:
            for constraint in constraints.constraints_for(item):
                result = constraint.satisfied_by(item)
                if not result.satisfied:
                    dissatifactions.append(result)
        return dissatifactions
