from collections.abc import Iterator
from ctypes import c_void_p
from types import TracebackType
from typing import Final, Literal, Self, SupportsIndex

from ._typing import _IntLike, _SupportsKeysAndGetItem, _VSValue
from .constants import SampleType
from .formats import ChannelLayout, VideoFormat
from .props import FrameProps

class FramePtr: ...

# These memoryview-likes don't exist at runtime.
class _video_view(memoryview):  # type: ignore[misc]
    def __getitem__(self, index: tuple[int, int]) -> float: ...  # type: ignore[override]
    def __setitem__(self, index: tuple[int, int], other: float) -> None: ...  # type: ignore[override]
    @property
    def shape(self) -> tuple[int, int]: ...
    @property
    def strides(self) -> tuple[int, int]: ...
    @property
    def ndim(self) -> Literal[2]: ...
    @property
    def obj(self) -> FramePtr: ...  # type: ignore[override]
    def tolist(self) -> list[float]: ...  # type: ignore[override]

class _audio_view(memoryview):  # type: ignore[misc]
    def __getitem__(self, index: int) -> float: ...  # type: ignore[override]
    def __setitem__(self, index: int, other: float) -> None: ...  # type: ignore[override]
    @property
    def shape(self) -> tuple[int]: ...
    @property
    def strides(self) -> tuple[int]: ...
    @property
    def ndim(self) -> Literal[1]: ...
    @property
    def obj(self) -> FramePtr: ...  # type: ignore[override]
    def tolist(self) -> list[float]: ...  # type: ignore[override]

class RawFrame:
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __enter__(self) -> Self: ...
    def __exit__(
        self, exc: type[BaseException] | None = None, val: BaseException | None = None, tb: TracebackType | None = None
    ) -> bool | None: ...
    def __getitem__(self, index: SupportsIndex) -> memoryview: ...
    def __len__(self) -> int: ...
    @property
    def closed(self) -> bool: ...
    @property
    def props(self) -> FrameProps: ...
    @props.setter
    def props(self, new_props: _SupportsKeysAndGetItem[str, _VSValue]) -> None: ...
    @property
    def readonly(self) -> bool: ...
    def copy(self) -> Self: ...
    def close(self) -> None: ...
    def get_write_ptr(self, plane: _IntLike) -> c_void_p: ...
    def get_read_ptr(self, plane: _IntLike) -> c_void_p: ...
    def get_stride(self, plane: _IntLike) -> int: ...

# Behave like a Sequence
class VideoFrame(RawFrame):
    format: Final[VideoFormat]
    width: Final[int]
    height: Final[int]

    def __getitem__(self, index: SupportsIndex) -> _video_view: ...
    def readchunks(self) -> Iterator[_video_view]: ...

# Behave like a Sequence
class AudioFrame(RawFrame):
    sample_type: Final[SampleType]
    bits_per_sample: Final[int]
    bytes_per_sample: Final[int]
    channel_layout: Final[int]
    num_channels: Final[int]

    def __getitem__(self, index: SupportsIndex) -> _audio_view: ...
    @property
    def channels(self) -> ChannelLayout: ...
