from typing import List, Optional, Tuple, Union

# Type aliases for Rust library types
Pixel = int
Point = Tuple[float, float]
Vector = Tuple[float, float]

# Python 2D array type alias
Matrix = List[List[float]]

class SpotShape:
    def __init__(self, src: Union[None, float, Vector, Matrix] = None) -> None: ...
    def scale(self, k: float) -> SpotShape: ...
    def stretch(self, kx: float, ky: float) -> SpotShape: ...
    def rotate(self, phi: float) -> SpotShape: ...

# Token class
class SpotId:
    pass

class Transform:
    def __init__(self, src: Union[None, float, Vector, Matrix] = None) -> None: ...
    def translate(self, shift: Vector) -> Transform: ...
    def scale(self, k: float) -> Transform: ...
    def stretch(self, kx: float, ky: float) -> Transform: ...
    def rotate(self, phi: float) -> Transform: ...
    def compose(self, t: Transform) -> Transform: ...

class Window:
    def __init__(self, src: Tuple[Tuple[int, int], Tuple[int, int]]) -> None: ...
    @staticmethod
    def new(width: int, height: int) -> Window: ...
    def at(self, x: int, y: int) -> Window: ...

class ImageFormat:
    RawGamma8Bpp: ImageFormat = ...
    RawLinear10BppLE: ImageFormat = ...
    RawLinear12BppLE: ImageFormat = ...
    PngGamma8Bpp: ImageFormat = ...
    PngLinear16Bpp: ImageFormat = ...

class Canvas:
    PIXEL_MAX: Pixel = ...
    @staticmethod
    def new(width: int, height: int) -> Canvas: ...
    def add_spot(
        self, position: Point, shape: SpotShape, intensity: float
    ) -> SpotId: ...
    def spot_position(self, spot: SpotId) -> Optional[Point]: ...
    def spot_intensity(self, spot: SpotId) -> Optional[float]: ...
    def set_spot_offset(self, spot: SpotId, offset: Vector) -> None: ...
    def set_spot_illumination(self, spot: SpotId, illumination: float) -> None: ...
    def clear(self) -> None: ...
    def draw(self) -> None: ...
    def dimensions(self) -> Tuple[int, int]: ...
    def set_background(self, level: Pixel) -> None: ...
    def set_view_transform(self, transform: Transform) -> None: ...
    def set_brightness(self, brightness: float) -> None: ...
    def export_image(self, format: ImageFormat) -> bytes: ...
    def export_window_image(self, window: Window, format: ImageFormat) -> bytes: ...
    def export_subsampled_image(self, factors: Tuple[int, int], format: ImageFormat) -> bytes: ...
