from dataclasses import field
from enum import Enum
from typing import Annotated

from flet.controls.animation import AnimationCurve
from flet.controls.base_control import control
from flet.controls.control import Control
from flet.controls.duration import Duration, DurationValue
from flet.controls.layout_control import LayoutControl
from flet.utils.validation import V

__all__ = ["AnimatedSwitcher", "AnimatedSwitcherTransition"]


class AnimatedSwitcherTransition(Enum):
    """
    Visual transition strategy used by :attr:`flet.AnimatedSwitcher.transition`.

    Controls how old and new content are animated while the switch occurs.
    """

    FADE = "fade"
    """
    Cross-fades between outgoing and incoming content.
    """

    ROTATION = "rotation"
    """
    Rotates content during the switch.
    """

    SCALE = "scale"
    """
    Scales content during the switch.
    """


@control("AnimatedSwitcher")
class AnimatedSwitcher(LayoutControl):
    """
    Used to switch between controls with an animation.
    """

    content: Annotated[
        Control,
        V.visible_control(),
    ]
    """
    The content to display.

    When it changes, this switcher will animate the transition from the old/previous
    `content` to the new one.

    Raises:
        ValueError: If it is not visible.
    """

    duration: DurationValue = field(default_factory=lambda: Duration(seconds=1))
    """
    The duration of the transition from the old :attr:`content` to the new one.
    """

    reverse_duration: DurationValue = field(default_factory=lambda: Duration(seconds=1))
    """
    The duration of the transition from the new :attr:`content` to the old one.
    """

    switch_in_curve: AnimationCurve = AnimationCurve.LINEAR
    """
    The animation curve to use when transitioning in a new :attr:`content`.
    """

    switch_out_curve: AnimationCurve = AnimationCurve.LINEAR
    """
    The animation curve to use when transitioning an old :attr:`content` out.
    """

    transition: AnimatedSwitcherTransition = AnimatedSwitcherTransition.FADE
    """
    An animation type to transition between new and old :attr:`content`.
    """
