from dataclasses import dataclass
from typing import Union


@dataclass(frozen = True)
class ParameterSpecification:
    """
    Class to specify the conditions of a parameter
    that must be used within a node, including the
    type, the default value if existing, or a
    minimum and/or maximum value if set.

    A type that is not orderable not comparable 
    must not include `min` nor `max` parameter or
    an exception will be raised. 
    """

    name: str
    """
    The name of the parameter to set, that must be
    unique for that specific node and method.
    """
    # TODO: Set the type (?)
    type: any
    """
    The type of parameter we are accepting, that
    can be `float`, `int`, `str`, etc.
    """
    is_required: bool = False
    """
    Boolean flag to indicate if this parameter is
    required (mandatory) or not (optional).
    """
    default: Union[any, None] = None
    """
    The default value we want for this parameter,
    that will be used if the user doesn't provide
    a value.
    """
    min: Union[float, None] = None
    """
    The minimum possible value for this parameter,
    that can be `None` if we accept any value (if
    we don't want to limit it).
    """
    max: Union[float, None] = None
    """
    The maximum possible value for this parameter,
    that can be `None` if we accept any value (if
    we don't want to limit it).
    """

    def __post_init__(
        self
    ):
        if (
            self.default is not None and
            self.min is not None and
            self.default < self.min
        ):
            raise Exception('The default value provided is under the minimum.')
        
        if (
            self.default is not None and
            self.max is not None and
            self.default > self.max
        ):
            raise Exception('The default value provided is over the maximum.')

