from yta_editor.transformations.effects.abstract import EffectParameters
from yta_editor.transformations.effects.video import VideoEffect
from yta_editor_nodes.processor import BrightnessNodeProcessor
from yta_editor_utils.texture import TextureUtils
from yta_editor_time.evaluation_context import EvaluationContext
from yta_editor_parameters.values.abstract import VideoEditorParameterValue
from yta_editor_parameters.values import ConstantVideoEditorParameterValue
from yta_validation.parameter import ParameterValidator
from typing import Union
from dataclasses import dataclass


# TODO: We need to define all the specific effect
# params to be able to build them properly missing
# no fields
@dataclass
class BrightnessVideoEffectParameters(EffectParameters):
    """
    The parameters to use when applying the effect
    that changes the brightness for a specific
    `ealuation_context`.

    This will be returned by the effect when
    calculated, for a specific `evaluation_context`.
    """

    def __init__(
        self,
        brightness: float
    ):
        self.brightness: float = brightness
        """
        The value to apply as brightness.
        """
        

class BrightnessVideoEffect(VideoEffect):
    """
    The effect that will change the brightness of the
    element according to the provided conditions.
    """

    def __init__(
        self,
        do_use_gpu: bool = True,
        # TODO: Use 'factor' instead
        brightness: VideoEditorParameterValue = ConstantVideoEditorParameterValue(2.0)
    ):
        ParameterValidator.validate_mandatory_bool('do_use_gpu', do_use_gpu)
        ParameterValidator.validate_mandatory_instance_of('brightness', brightness, VideoEditorParameterValue)

        self.do_use_gpu: bool = do_use_gpu
        """
        Flag to indicate if using GPU or not.
        """
        # TODO: Maybe 'parse_params' (?)
        self.brightness: VideoEditorParameterValue = brightness
        """
        The `VideoEditorParameterValue` that defines the value that
        should be applied for the specific `evaluation_context`
        requested.
        """

    def _get_params_at(
        self,
        evaluation_context: EvaluationContext
    ) -> BrightnessVideoEffectParameters:
        """
        *For internal use only*

        Get the parameters that must be applied at the given
        `evaluation_context`.
        """
        ParameterValidator.validate_mandatory_instance_of('evaluation_context', evaluation_context, EvaluationContext)

        return BrightnessVideoEffectParameters(
            # TODO: Use 'factor' instead
            brightness = self.brightness.evaluate(
                evaluation_context = evaluation_context
            )
        )
    
    def _apply(
        self,
        # TODO: Set the type
        frame: any,
        output_size: Union[tuple[int, int], None],
        evaluation_context: EvaluationContext
    # TODO: Set the type
    ) -> any:
        parameters = self._get_params_at(
            evaluation_context = evaluation_context
        )

        if parameters.brightness == 1.0:
            return frame
            return TextureUtils.numpy_to_uint8(frame)
        
        return BrightnessNodeProcessor(
            # TODO: What do I do with the 'opengl_context' (?)
            opengl_context = None
        ).process(
            inputs = {
                'base_input': frame
            },
            evaluation_context = evaluation_context,
            do_use_gpu = self.do_use_gpu,
            output_size = output_size,
            # parameters = parameters
            # TODO: Use 'factor' instead
            parameters = {
                'factor': parameters.brightness
            }
        )