"""UVC controller abstract base class."""

from __future__ import annotations

from abc import ABC, abstractmethod
from dataclasses import dataclass
from enum import Enum, auto


class UvcParam(Enum):
    """UVC video proc amp controls supported by the ELP camera."""
    BRIGHTNESS = auto()
    CONTRAST = auto()
    SATURATION = auto()
    HUE = auto()
    SHARPNESS = auto()
    GAMMA = auto()
    WHITE_BALANCE = auto()
    BACKLIGHT_COMPENSATION = auto()
    EXPOSURE = auto()


@dataclass
class UvcParamInfo:
    """Range and current value of a single UVC control."""
    param: UvcParam
    supported: bool
    minimum: int = 0
    maximum: int = 100
    default: int = 50
    current: int = 50
    step: int = 1
    auto_supported: bool = False
    auto_enabled: bool = False


class UvcControllerBase(ABC):
    """
    Abstract interface for platform-specific UVC camera controls.

    All set_* methods are best-effort: if a control is unsupported the
    call should silently do nothing (log at DEBUG level).
    """

    @abstractmethod
    def open(self, device_name: str) -> bool:
        """Open connection to the named camera device. Returns True on success."""

    @abstractmethod
    def close(self) -> None:
        """Release the camera device handle."""

    @abstractmethod
    def is_open(self) -> bool:
        """Return True if the device is currently open."""

    @abstractmethod
    def get_param_info(self, param: UvcParam) -> UvcParamInfo:
        """Return range + current value for the given control."""

    @abstractmethod
    def get_all_params(self) -> list[UvcParamInfo]:
        """Return info for all known UVC controls."""

    @abstractmethod
    def set_value(self, param: UvcParam, value: int) -> bool:
        """
        Set a control to an integer value.
        Returns True if the call succeeded.
        """

    @abstractmethod
    def set_auto(self, param: UvcParam, enabled: bool) -> bool:
        """
        Enable/disable auto mode for a control (e.g. auto white balance).
        Returns True if supported and the call succeeded.
        """
