"""
Some explanations to let you understand it better:
Entrada (t): tiempo normalizado en [0, 1].
Salida (a): progreso no lineal en [0, 1].
"""
from yta_math_easings.abstract import EasingFunction
from yta_validation.parameter import ParameterValidator
from abc import ABC


class EasingAnimatedFunction(ABC):
    """
    *Abstract class*

    Abstract class to be inherited by the specific
    easing implementations.

    An easing function that is able to calculate a
    value according to the `n` parameter provided,
    but within a range of possible values and
    according to the duration set.

    The `t` value is representing the time lapsed
    for the easing function, as a normalized value
    in the `[0.0, 1.0]` range.

    The `a` value is representing the progress for
    the easing function, as a normalized value in
    the `[0.0, 1.0]` range.
    """
    _limit = (0, 1)
    """
    *For internal use only*

    The limit of the alpha value we can use.
    """

    def __init__(
        self,
        start_value: float,
        end_value: float,
        duration: float,
        easing_function: EasingFunction
    ):
        ParameterValidator.validate_mandatory_positive_number('duration', duration, do_include_zero = False)
        ParameterValidator.validate_mandatory_instance_of('easing_function', easing_function, EasingFunction)

        self.start_value: float = start_value
        """
        The start value of the valid range of the animated
        easing function.
        """
        self.end_value: float = end_value
        """
        The end value of the valid range of the animated
        easing function.
        """
        self.duration: float = duration
        """
        The total duration (in seconds) that the animated
        easing will take to go from the `start_value`
        to the `end_value`, that can be used to calculate
        the different values at the different time moments
        requested by the user.
        """
        self._easing_function: EasingFunction = easing_function
        """
        The easing function associated to this animated
        easing function, that will be the one used to
        calculate the values according to the definition.
        """
        
    def func(
        self,
        n: float,
        **kwargs
    ) -> float:
        """
        Alias for the `get_progress_from_t` function.
        """
        return self.get_progress_from_t(
            t = n,
            **kwargs
        )

    def get_progress_from_t(
        self,
        t: float,
        **kwargs
    ) -> float:
        """
        Also called `func`.

        Apply the easing to the `t` value provided, that is
        the time but normalized, so it must be a value in
        the `[0.0, 1.0]` range, and get the normalized
        `progress` associated to it based on the specific
        easing function you are using.

        The `t` represents the time but normalized, and the
        returned `a` will be the progress done in that period
        of time.
        """
        ParameterValidator.validate_mandatory_number_between(
            name = 't',
            value = t,
            lower_limit = 0.0,
            upper_limit = 1.0,
            do_include_lower_limit = True,
            do_include_upper_limit = True
        )

        return self._easing_function.func(
            t,
            **kwargs
        )
    
    def ease(
        self,
        alpha: float,
        **kwargs
    ) -> float:
        """
        Alias for the `get_t_from_progress` function.
        """
        return self.get_t_from_progress(
            progress = alpha,
            **kwargs
        )
    
    def get_t_from_progress(
        self,
        progress: float,
        **kwargs
    ) -> float:
        """
        Also called `ease` function.

        Get the `t` real time moment that is associated to
        the `progress` normalized value provided, according
        to the internal `start_value` and `end_value`.

        The `progress` must be a normalized value in the 
        `[0.0, 1.0]` range.
        """
        ParameterValidator.validate_mandatory_number_between(
            name = 'progress',
            value = progress,
            lower_limit = 0.0,
            upper_limit = 1.0,
            do_include_lower_limit = True,
            do_include_upper_limit = True
        )

        t = self._limit[0] * (1 - progress) + self._limit[1] * progress
        t /= self.duration
        progress = self.get_progress_from_t(
            t = t,
            **kwargs
        )

        return self.end_value * progress + self.start_value * (1 - progress)
    
    def __call__(self, alpha: float) -> float:
        """
        Special method to allow us doing
        `AnimatedEasingFunction.ease(alpha)` directly.
        """

        """
        permite escribir:
        value = animation(alpha)
        en lugar de:
        value = animation.ease(alpha)
        """
        return self.get_t_from_progress(alpha)