"""
Embedding backend protocol definition.

All embedding backends (LSB, DCT, audio, video, etc.) implement this protocol,
enabling registry-based dispatch instead of if/elif chains.
"""

from __future__ import annotations

from typing import Any, Protocol, runtime_checkable


@runtime_checkable
class EmbeddingBackend(Protocol):
    """Protocol that all embedding backends must satisfy.

    Each backend handles a specific embedding mode (e.g. 'lsb', 'dct',
    'audio_lsb', 'audio_spread') for a specific carrier type ('image',
    'audio', 'video').
    """

    @property
    def mode(self) -> str:
        """The embedding mode identifier (e.g. 'lsb', 'dct')."""
        ...

    @property
    def carrier_type(self) -> str:
        """The carrier media type: 'image', 'audio', or 'video'."""
        ...

    def is_available(self) -> bool:
        """Whether this backend's dependencies are installed."""
        ...

    def embed(
        self,
        data: bytes,
        carrier: bytes,
        key: bytes,
        *,
        progress_file: str | None = None,
        **options: Any,
    ) -> tuple[bytes, Any]:
        """Embed data into a carrier.

        Args:
            data: Encrypted payload bytes.
            carrier: Raw carrier file bytes (image, audio, etc.).
            key: Derived key for pixel/sample selection.
            progress_file: Optional progress file path.
            **options: Backend-specific options (bits_per_channel,
                       output_format, color_mode, chip_tier, etc.).

        Returns:
            Tuple of (stego carrier bytes, embed stats).
        """
        ...

    def extract(
        self,
        carrier: bytes,
        key: bytes,
        *,
        progress_file: str | None = None,
        **options: Any,
    ) -> bytes | None:
        """Extract data from a carrier.

        Args:
            carrier: Stego carrier file bytes.
            key: Derived key for pixel/sample selection.
            progress_file: Optional progress file path.
            **options: Backend-specific options.

        Returns:
            Extracted payload bytes, or None if no payload found.
        """
        ...

    def calculate_capacity(self, carrier: bytes, **options: Any) -> int:
        """Calculate maximum embeddable payload size in bytes.

        Args:
            carrier: Raw carrier file bytes.
            **options: Backend-specific options (e.g. bits_per_channel).

        Returns:
            Maximum payload capacity in bytes.
        """
        ...
