from .modeltest import Criterion


class Range(Criterion):
    """
    Range criterion.

    True if the test quantity is within the range [lower, upper].

    Parameters
    ----------

    lower: float
        Lower boundary of range.

    upper: float
        Upper boundary of range.
    """
    def __init__(self, lower, upper):
        self.lower = lower
        self.upper = upper

    def __call__(self, value):
        return self.lower <= value < self.upper

    def __repr__(self):
        return "{}({}, {})".format(self.__class__.__name__, self.lower, self.upper)


class GreaterThan(Criterion):
    """
    Greater than criterion.

    True if the test quantity is greater than lower.

    Parameters
    ----------

    lower: float
        Quantity has to be strictly greater than lower to yield "true".
    """
    def __init__(self, lower):
        self.lower = lower

    def __call__(self, value):
        return self.lower < value

    def __repr__(self):
        return "{}({})".format(self.__class__.__name__, self.lower)


class LessThan(Criterion):
    """
    Greater than criterion.

    True if the test quantity is less then upper.

    Parameters
    ----------

    upper: float
        Quantity has to be strictly less then upper to yield true.
    """
    def __init__(self, upper):
        self.upper = upper

    def __call__(self, value):
        return value < self.upper

    def __repr__(self):
        return "{}({})".format(self.__class__.__name__, self.upper)


class TrueCriterion(Criterion):
    """
    Return True if the test quantity itself is True.
    """
    def __call__(self, value):
        return value

    def __repr__(self):
        return "{}()".format(self.__class__.__name__)
