from yta_multimedia.video.edition.effect.m_effect import MEffect as Effect
from yta_multimedia.video.position import Position
from yta_multimedia.video.edition.effect.moviepy.mask import ClipGenerator
from yta_multimedia.video import VideoHandler
from yta_multimedia.video.edition.effect.moviepy.position.objects.coordinate import Coordinate
from yta_multimedia.video.parser import VideoParser
from yta_multimedia.video.edition.effect.moviepy.position.utils.shake import shake_decreasing_movement
from yta_general_utils.programming.parameter_validator import PythonValidator
from moviepy.Clip import Clip
from moviepy import CompositeVideoClip
from typing import Union


class ShakeDecreasingAtPositionEffect(Effect):
    """
    This effect will blur the whole clip. The greater the
    'blur_radius' is, the more blurred it becomes.
    """
    def apply(self, video: Clip, position: Union[Position, Coordinate, tuple] = Position.CENTER) -> Clip:
        # TODO: This is not working properly yet
        #PythonValidator.validate_method_params(BlurEffect.apply, locals(), ['video'])
        background_video = ClipGenerator.get_default_background_video()

        return self.apply_over_video(video, background_video, position)
    
    # TODO: What about this (?)
    def apply_over_video(self, video: Clip, background_video: Clip, position: Union[Position, Coordinate] = Position.CENTER) -> Clip:
        video = VideoParser.to_moviepy(video)
        background_video = VideoParser.to_moviepy(background_video)

        # TODO: Validate position

        if PythonValidator.is_tuple(position):
            position = Coordinate(position[0], position[1])

        # Turn position into upper left moviepy position
        if PythonValidator.is_instance(position, Position):
            position = position.get_moviepy_upper_left_corner_tuple(video.size, background_video.size)
        elif PythonValidator.is_instance(position, Coordinate):
            position = position.get_moviepy_upper_left_corner_tuple(video.size, background_video.size)

        video_handler = VideoHandler(video)
        background_video = video_handler.prepare_background_clip(background_video)

        # TODO: What if I want to shake it while moving (?)

        video = video.with_position(lambda t: shake_decreasing_movement(t, position[0], position[1])).with_start(0).with_duration(video.duration)
        
        return CompositeVideoClip([
            background_video,
            video
        ])