from abc import ABC, abstractmethod
from typing import List, Optional, Sequence, Tuple, Union

from pygame.surface import Surface

def get_backends() -> List[str]: ...
def init(backend: Optional[str] = None) -> None: ...
def quit() -> None: ...
def list_cameras() -> List[str]: ...

class AbstractCamera(ABC):
    @abstractmethod
    def __init__(self, *args, **kwargs) -> None: ...
    @abstractmethod
    def start(self) -> None: ...
    @abstractmethod
    def stop(self) -> None: ...
    @abstractmethod
    def get_size(self) -> Tuple[int, int]: ...
    @abstractmethod
    def query_image(self) -> bool: ...
    @abstractmethod
    def get_image(self, dest_surf: Optional[Surface] = None) -> Surface: ...
    @abstractmethod
    def get_raw(self) -> bytes: ...
    # set_controls and get_controls are not a part of the AbstractCamera ABC,
    # because implementations of the same can vary across different Camera
    # types

class Camera(AbstractCamera):
    def __init__(
        self,
        device: Union[str, int] = 0,
        size: Union[Tuple[int, int], Sequence[int]] = (640, 480),
        format: str = "RGB",
    ) -> None: ...
    def start(self) -> None: ...
    def stop(self) -> None: ...
    def get_controls(self) -> Tuple[bool, bool, int]: ...
    def set_controls(
        self,
        hflip: bool = ...,
        vflip: bool = ...,
        brightness: int = ...,
    ) -> Tuple[bool, bool, int]: ...
    def get_size(self) -> Tuple[int, int]: ...
    def query_image(self) -> bool: ...
    def get_image(self, surface: Optional[Surface] = None) -> Surface: ...
    def get_raw(self) -> bytes: ...
