import cython

from .advertisement_tracker cimport AdvertisementTracker
from .auto_scheduler cimport ActiveScanRequest, AutoScanScheduler
from .base_scanner cimport BaseHaScanner
from .models cimport BluetoothServiceInfoBleak

cdef int NO_RSSI_VALUE
cdef int ADV_RSSI_SWITCH_THRESHOLD
cdef double TRACKER_BUFFERING_WOBBLE_SECONDS
cdef double FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS
cdef double _DURABLY_GONE_STALE_FACTOR
cdef int _STRONG_OWNER_STALE_RSSI
cdef double _RSSI_SMOOTHING_FACTOR
cdef int _ADV_RSSI_SWITCH_DEADBAND
cdef object FILTER_UUIDS
cdef object AdvertisementData
cdef object BLEDevice
cdef bint TYPE_CHECKING
cdef set APPLE_START_BYTES_WANTED

cdef unsigned char APPLE_IBEACON_START_BYTE
cdef unsigned char APPLE_HOMEKIT_START_BYTE
cdef unsigned char APPLE_HOMEKIT_NOTIFY_START_BYTE
cdef unsigned char APPLE_DEVICE_ID_START_BYTE
cdef unsigned char APPLE_FINDMY_START_BYTE

cdef object APPLE_MFR_ID

@cython.locals(uuids=set)
cdef _dispatch_bleak_callback(
    BleakCallback bleak_callback,
    object device,
    object advertisement_data
)

cdef class BleakCallback:

    cdef public object callback
    cdef public dict filters


cdef class BluetoothManager:

    cdef public object _cancel_unavailable_tracking
    cdef public AdvertisementTracker _advertisement_tracker
    cdef public dict _fallback_intervals
    cdef public dict _intervals
    cdef public dict _unavailable_callbacks
    cdef public dict _connectable_unavailable_callbacks
    cdef public set _bleak_callbacks
    cdef public dict _all_history
    cdef public dict _connectable_history
    cdef public dict _smoothed_rssi
    cdef public dict _demoted_source
    cdef public dict _name_cache
    cdef public set _non_connectable_scanners
    cdef public set _connectable_scanners
    cdef public dict _adapters
    cdef public dict _sources
    cdef public object _bluetooth_adapters
    cdef public object slot_manager
    cdef public bint _debug
    cdef public bint shutdown
    cdef public object _loop
    cdef public object _adapter_refresh_future
    cdef public object _recovery_lock
    cdef public set _disappeared_callbacks
    cdef public dict _allocations_callbacks
    cdef public object _cancel_allocation_callbacks
    cdef public dict _adapter_sources
    cdef public dict _allocations
    cdef public dict _scanner_registration_callbacks
    cdef public dict _scanner_mode_change_callbacks
    cdef public set _warned_passive_active_scan
    cdef public object _subclass_discover_info
    cdef public bint has_advertising_side_channel
    cdef public dict _side_channel_scanners
    cdef public object _mgmt_ctl
    # _auto_scheduler stays untyped to avoid a typed cdef field that
    # triggers Cython's type-import path during manager init; the hot
    # path casts to AutoScanScheduler via cython.locals on
    # _scanner_adv_received so the call into on_advertisement is still
    # a direct vtable dispatch.
    cdef public object _auto_scheduler

    @cython.locals(
        stale_seconds=double,
        elapsed=double,
        durably_gone=double,
        comparable_or_stronger=bint,
        owner_strong=bint,
        old_rssi=double,
        switch_margin=int,
    )
    cdef bint _prefer_previous_adv_from_different_source(
        self,
        BluetoothServiceInfoBleak old,
        BluetoothServiceInfoBleak new,
        dict smoothed,
        double new_rssi,
        bint record_demotion
    )

    @cython.locals(scanner=BaseHaScanner)
    cdef bint _should_keep_previous_adv(
        self,
        BluetoothServiceInfoBleak old_info,
        BluetoothServiceInfoBleak new_info,
        dict smoothed,
        double new_rssi,
        bint record_demotion
    )

    @cython.locals(
        cached=str,
        cached_cf=str,
        name_cf=str,
        cached_len=Py_ssize_t,
        name_len=Py_ssize_t,
    )
    cdef void _update_name_cache(self, str address, str name)

    cdef void _handle_name_cache_miss(
        self,
        BluetoothServiceInfoBleak service_info,
        str cached_name,
    )

    cpdef void scanner_adv_received(self, BluetoothServiceInfoBleak service_info)

    @cython.locals(
        old_service_info=BluetoothServiceInfoBleak,
        old_connectable_service_info=BluetoothServiceInfoBleak,
        source=str,
        connectable=bint,
        apple_cstr="const unsigned char *",
        bleak_callback=BleakCallback,
        cached_name=str,
        auto_scheduler=AutoScanScheduler,
        smoothed_bucket=dict,
        prev_smoothed=object,
        prev_double=double,
        new_smoothed=double,
        rssi=int,
    )
    cdef void _scanner_adv_received(self, BluetoothServiceInfoBleak service_info)

    cpdef _async_describe_source(self, BluetoothServiceInfoBleak service_info)

    cpdef void _unregister_source_callback(
        self,
        dict callbacks_dict,
        object source,
        object callback,
    ) except *

    cdef void _dispatch_source_callbacks(
        self,
        dict callbacks_dict,
        object source,
        object payload,
        str label,
    ) except *
