"""
-----------------------
BlueZ backend arguments
-----------------------
"""

from typing import NamedTuple, TypedDict, Union

from bleak.assigned_numbers import AdvertisementDataType


class BlueZDiscoveryFilters(TypedDict, total=False):
    """
    Dictionary of arguments for the ``org.bluez.Adapter1.SetDiscoveryFilter``
    D-Bus method.

    https://github.com/bluez/bluez/blob/master/doc/org.bluez.Adapter.rst#void-setdiscoveryfilterdict-filter
    """

    UUIDs: list[str]
    """
    Filter by service UUIDs, empty means match _any_ UUID.

    Normally, the ``service_uuids`` argument of :class:`bleak.BleakScanner`
    is used instead.
    """
    RSSI: int
    """
    RSSI threshold value.
    """
    Pathloss: int
    """
    Pathloss threshold value.
    """
    Transport: str
    """
    Transport parameter determines the type of scan.

    This should not be used since it is required to be set to ``"le"``.
    """
    DuplicateData: bool
    """
    Disables duplicate detection of advertisement data.

    This does not affect the ``Filter Duplicates`` parameter of the ``LE Set Scan Enable``
    HCI command to the Bluetooth adapter!

    Although the default value for BlueZ is ``True``, Bleak sets this to ``False`` by default.
    """
    Discoverable: bool
    """
    Make adapter discoverable while discovering,
    if the adapter is already discoverable setting
    this filter won't do anything.
    """
    Pattern: str
    """
    Discover devices where the pattern matches
    either the prefix of the address or
    device name which is convenient way to limited
    the number of device objects created during a
    discovery.
    """


class OrPattern(NamedTuple):
    """
    BlueZ advertisement monitor or-pattern.

    https://github.com/bluez/bluez/blob/master/doc/org.bluez.AdvertisementMonitor.rst#arrayuint8-uint8-arraybyte-patterns-read-only-optional
    """

    start_position: int
    ad_data_type: AdvertisementDataType
    content_of_pattern: bytes


# Windows has a similar structure, so we allow generic tuple for cross-platform compatibility
OrPatternLike = Union[OrPattern, tuple[int, AdvertisementDataType, bytes]]


class BlueZScannerArgs(TypedDict, total=False):
    """
    :class:`BleakScanner` args that are specific to the BlueZ backend.
    """

    adapter: str
    """
    Bluetooth adapter to use for discovery, e.g. "hci0".

    .. tip:: If you have multiple Bluetooth adapters, they may not always be
         assigned the same ``hciX`` name across reboots. In that case, you can
         use udev to look up the name based on other properties like the USB
         vendor and product ID.

    .. versionadded:: 3.0
    """

    filters: BlueZDiscoveryFilters
    """
    Filters to pass to the adapter SetDiscoveryFilter D-Bus method.

    Only used for active scanning.
    """

    or_patterns: list[OrPatternLike]
    """
    Or patterns to pass to the AdvertisementMonitor1 D-Bus interface.

    Only used for passive scanning.
    """


class BlueZClientArgs(TypedDict, total=False):
    """
    :class:`bleak.BleakClient` args that are specific to the BlueZ backend.

    .. versionadded:: 3.0
    """

    adapter: str
    """
    Bluetooth adapter to use for connection, e.g. "hci0".

    .. tip:: If you have multiple Bluetooth adapters, they may not always be
         assigned the same ``hciX`` name across reboots. In that case, you can
         use udev to look up the name based on other properties like the USB
         vendor and product ID.
    """


class BlueZNotifyArgs(TypedDict, total=False):
    """
    :meth:`bleak.BleakClient.start_notify` method args that are specific to the
    BlueZ backend.

    .. versionadded:: 2.1
    """

    use_start_notify: bool
    """
    If false, use the "AcquireNotify" D-Bus method instead of "StartNotify" to
    subscribe to notifications. The default is to use "StartNotify" for better
    compatibility with most BLE devices.

    see :ref:`linux-start-notify` for more details.

    .. versionchanged:: 3.0.2
        The default value was changed from ``False`` to ``True``.
    """
