from __future__ import annotations

from enum import Enum
from typing import Optional


class XFade(str, Enum):
    """All FFmpeg xfade transition names (FFmpeg 6.x, indices 0-57)."""

    FADE = "fade"
    WIPELEFT = "wipeleft"
    WIPERIGHT = "wiperight"
    WIPEUP = "wipeup"
    WIPEDOWN = "wipedown"
    SLIDELEFT = "slideleft"
    SLIDERIGHT = "slideright"
    SLIDEUP = "slideup"
    SLIDEDOWN = "slidedown"
    CIRCLECROP = "circlecrop"
    RECTCROP = "rectcrop"
    DISTANCE = "distance"
    FADEBLACK = "fadeblack"
    FADEWHITE = "fadewhite"
    RADIAL = "radial"
    SMOOTHLEFT = "smoothleft"
    SMOOTHRIGHT = "smoothright"
    SMOOTHUP = "smoothup"
    SMOOTHDOWN = "smoothdown"
    CIRCLEOPEN = "circleopen"
    CIRCLECLOSE = "circleclose"
    VERTOPEN = "vertopen"
    VERTCLOSE = "vertclose"
    HORZOPEN = "horzopen"
    HORZCLOSE = "horzclose"
    DISSOLVE = "dissolve"
    PIXELIZE = "pixelize"
    DIAGTL = "diagtl"
    DIAGTR = "diagtr"
    DIAGBL = "diagbl"
    DIAGBR = "diagbr"
    HLSLICE = "hlslice"
    HRSLICE = "hrslice"
    VUSLICE = "vuslice"
    VDSLICE = "vdslice"
    HBLUR = "hblur"
    FADEGRAYS = "fadegrays"
    WIPETL = "wipetl"
    WIPETR = "wipetr"
    WIPEBL = "wipebl"
    WIPEBR = "wipebr"
    SQUEEZEH = "squeezeh"
    SQUEEZEV = "squeezev"
    ZOOMIN = "zoomin"
    FADEFAST = "fadefast"
    FADESLOW = "fadeslow"
    HLWIND = "hlwind"
    HRWIND = "hrwind"
    VUWIND = "vuwind"
    VDWIND = "vdwind"
    COVERLEFT = "coverleft"
    COVERRIGHT = "coverright"
    COVERUP = "coverup"
    COVERDOWN = "coverdown"
    REVEALLEFT = "revealleft"
    REVEALRIGHT = "revealright"
    REVEALUP = "revealup"
    REVEALDOWN = "revealdown"


_XFADE_NAMES: set[str] = {t.value for t in XFade}


def resolve_xfade(value: XFade | str) -> str:
    """Resolve a transition value to a valid FFmpeg xfade name string."""
    if isinstance(value, XFade):
        return value.value
    low = value.lower()
    if low not in _XFADE_NAMES:
        raise ValueError(
            f"Unknown xfade transition: {value!r}. "
            f"Choose from: {', '.join(sorted(_XFADE_NAMES))}"
        )
    return low


class Transition:
    """Clip-level fade in/out (VideoDB compatible) OR xfade between clips.

    Used in two contexts:

    1. Clip-level (VideoDB style)::

        Transition(in_="fade", out="fade", duration=2)

    2. As an xfade enum constant for ``track.add_clip()``::

        track.add_clip(5, clip, transition=Transition.DISSOLVE)
    """

    # Expose XFade members as class-level constants for convenience:
    # Transition.DISSOLVE, Transition.FADE, etc.
    FADE = XFade.FADE
    WIPELEFT = XFade.WIPELEFT
    WIPERIGHT = XFade.WIPERIGHT
    WIPEUP = XFade.WIPEUP
    WIPEDOWN = XFade.WIPEDOWN
    SLIDELEFT = XFade.SLIDELEFT
    SLIDERIGHT = XFade.SLIDERIGHT
    SLIDEUP = XFade.SLIDEUP
    SLIDEDOWN = XFade.SLIDEDOWN
    CIRCLECROP = XFade.CIRCLECROP
    RECTCROP = XFade.RECTCROP
    DISTANCE = XFade.DISTANCE
    FADEBLACK = XFade.FADEBLACK
    FADEWHITE = XFade.FADEWHITE
    RADIAL = XFade.RADIAL
    SMOOTHLEFT = XFade.SMOOTHLEFT
    SMOOTHRIGHT = XFade.SMOOTHRIGHT
    SMOOTHUP = XFade.SMOOTHUP
    SMOOTHDOWN = XFade.SMOOTHDOWN
    CIRCLEOPEN = XFade.CIRCLEOPEN
    CIRCLECLOSE = XFade.CIRCLECLOSE
    VERTOPEN = XFade.VERTOPEN
    VERTCLOSE = XFade.VERTCLOSE
    HORZOPEN = XFade.HORZOPEN
    HORZCLOSE = XFade.HORZCLOSE
    DISSOLVE = XFade.DISSOLVE
    PIXELIZE = XFade.PIXELIZE
    DIAGTL = XFade.DIAGTL
    DIAGTR = XFade.DIAGTR
    DIAGBL = XFade.DIAGBL
    DIAGBR = XFade.DIAGBR
    HLSLICE = XFade.HLSLICE
    HRSLICE = XFade.HRSLICE
    VUSLICE = XFade.VUSLICE
    VDSLICE = XFade.VDSLICE
    HBLUR = XFade.HBLUR
    FADEGRAYS = XFade.FADEGRAYS
    WIPETL = XFade.WIPETL
    WIPETR = XFade.WIPETR
    WIPEBL = XFade.WIPEBL
    WIPEBR = XFade.WIPEBR
    SQUEEZEH = XFade.SQUEEZEH
    SQUEEZEV = XFade.SQUEEZEV
    ZOOMIN = XFade.ZOOMIN
    FADEFAST = XFade.FADEFAST
    FADESLOW = XFade.FADESLOW
    HLWIND = XFade.HLWIND
    HRWIND = XFade.HRWIND
    VUWIND = XFade.VUWIND
    VDWIND = XFade.VDWIND
    COVERLEFT = XFade.COVERLEFT
    COVERRIGHT = XFade.COVERRIGHT
    COVERUP = XFade.COVERUP
    COVERDOWN = XFade.COVERDOWN
    REVEALLEFT = XFade.REVEALLEFT
    REVEALRIGHT = XFade.REVEALRIGHT
    REVEALUP = XFade.REVEALUP
    REVEALDOWN = XFade.REVEALDOWN

    def __init__(
        self,
        *,
        in_: Optional[str] = None,
        out: Optional[str] = None,
        duration: float = 1.0,
    ) -> None:
        self.in_ = in_
        self.out = out
        self.duration = duration

    def __repr__(self) -> str:
        parts: list[str] = []
        if self.in_:
            parts.append(f"in_={self.in_!r}")
        if self.out:
            parts.append(f"out={self.out!r}")
        parts.append(f"duration={self.duration}")
        return f"Transition({', '.join(parts)})"
