from enum import Flag, Enum
from typing import Callable

class AnimationFlip(Flag):
    NONE = 0
    VERTICAL = 1
    HORIZONTAL = 2
    BOTH = 3

class AnimationTrans(Enum):
    NONE = 0
    ADD = 1
    SUB = 2

class Clsn:
    _xmin: int
    _ymin: int
    _xmax: int
    _ymax: int
    _default: bool

    def __init__(self, xmin: int, ymin: int, xmax: int, ymax: int, default: bool = False): ...

class Frame:
    _group: int
    _index: int
    _length: int = -1
    _offset: tuple[int, int] = (0, 0)
    _flip: AnimationFlip = AnimationFlip.NONE
    _trans: AnimationTrans = AnimationTrans.NONE
    _scale: tuple[float, float] = (1, 1)
    _rotate: int = 0
    _loopstart: bool = False

    def __init__(self, 
                 group: int, index: int, length: int = -1, 
                 offset: tuple[int, int] = (0, 0), flip: AnimationFlip = AnimationFlip.NONE, trans: AnimationTrans = AnimationTrans.NONE,
                 scale: tuple[float, float] = (1, 1), rotate: int = 0):
        ...

    def compile(self) -> str: ...

    def clsn1(self, clsn: Clsn) -> Frame: ...
    def clsn2(self, clsn: Clsn) -> Frame: ...
    def default(self) -> Frame: ...

    def seq(self) -> Sequence: ...
    def dup(self) -> Frame: ...
    def length(self, length: int) -> Frame: ...
    def flip(self, flip: AnimationFlip) -> Frame: ...
    def rotate(self, rotate: int) -> Frame: ...
    def offset(self, offset: tuple[int, int]) -> Frame: ...
    def translate(self, offset: tuple[int, int]) -> Frame: ...
    def scale(self, scale: tuple[float, float]) -> Frame: ...
    def loop(self) -> Frame: ...

class SequenceModifier:
    def seq(self) -> Sequence: ...
    def set(self, val: int | Enum, filter: Callable[[Frame], bool] | None = None) -> SequenceModifier: ...
    def add(self, val: int | Enum, filter: Callable[[Frame], bool] | None = None) -> SequenceModifier: ...
    def mul(self, val: int | Enum, filter: Callable[[Frame], bool] | None = None) -> SequenceModifier: ...
    def transform(self, transformer: Callable[[Frame, int], int]) -> SequenceModifier: ...
    def extend(self, frames: Frame | list[Frame] | Sequence | SequenceModifier | FrameSequenceModifier | TupleSequenceModifier) -> SequenceModifier: ...
    def __getitem__(self, key: int | slice) -> SequenceModifier: ...

    @property
    def frames(self) -> FrameSequenceModifier: ...
    @property
    def group(self) -> SequenceModifier: ...
    @property
    def index(self) -> SequenceModifier: ...
    @property
    def length(self) -> SequenceModifier: ...
    @property
    def rotation(self) -> SequenceModifier: ...
    @property
    def offset(self) -> TupleSequenceModifier: ...
    @property
    def scale(self) -> TupleSequenceModifier: ...
    @property
    def flip(self) -> SequenceModifier: ...

class TupleSequenceModifier(SequenceModifier):
    def set(self, val: tuple[int, int], filter: Callable[[Frame], bool] | None = None) -> TupleSequenceModifier: ...
    def add(self, val: tuple[int, int], filter: Callable[[Frame], bool] | None = None) -> TupleSequenceModifier: ...
    def mul(self, val: tuple[int, int], filter: Callable[[Frame], bool] | None = None) -> TupleSequenceModifier: ...
    def transform(self, transformer: Callable[[Frame, tuple[int, int]], tuple[int, int]]) -> TupleSequenceModifier: ...

    def __getitem__(self, key: int | slice) -> TupleSequenceModifier: ...

class FrameSequenceModifier(SequenceModifier):
    def reverse(self) -> FrameSequenceModifier: ...
    def transform(self, transformer: Callable[[Frame], Frame]) -> FrameSequenceModifier: ...
    def clsn1(self, clsn: Clsn, filter: Callable[[Frame], bool] | None = None) -> FrameSequenceModifier: ...
    def clsn2(self, clsn: Clsn, filter: Callable[[Frame], bool] | None = None) -> FrameSequenceModifier: ...
    def default(self, filter: Callable[[Frame], bool] | None = None) -> FrameSequenceModifier: ...

    def __getitem__(self, key: int | slice) -> FrameSequenceModifier: ...

class Sequence:
    _frames: list[Frame]

    def __init__(self, frames: list[Frame]): ...
    def compile(self) -> str: ...
    def extend(self, frames: Frame | list[Frame] | Sequence | SequenceModifier | FrameSequenceModifier | TupleSequenceModifier) -> Sequence: ...
    def __getitem__(self, key: int | slice) -> Sequence: ...

    @property
    def frames(self) -> FrameSequenceModifier: ...
    @property
    def group(self) -> SequenceModifier: ...
    @property
    def index(self) -> SequenceModifier: ...
    @property
    def length(self) -> SequenceModifier: ...
    @property
    def rotation(self) -> SequenceModifier: ...
    @property
    def offset(self) -> TupleSequenceModifier: ...
    @property
    def scale(self) -> TupleSequenceModifier: ...
    @property
    def flip(self) -> SequenceModifier: ...

class Animation:
    _frames: Sequence
    _id: int | None = None

    def __init__(self, frames: Sequence | SequenceModifier | list[Frame] | Frame | None = None, id: int | None = None, external: bool = False): ...
    def compile(self) -> str: ...

    @property
    def sequence(self) -> FrameSequenceModifier: ...

__all__ = ["Animation", "Sequence", "Frame", "AnimationFlip", "AnimationTrans"]