from typing import Tuple, Union, overload, Optional, Literal, List

######### stubs for RF24 bindings ###########################################

RF24_DRIVER: Literal["SPIDEV", "wiringPi", "pigpio", "MRAA", "RPi"]

class rf24_crclength_e:
    RF24_CRC_DISABLED: "rf24_crclength_e"
    RF24_CRC_8: "rf24_crclength_e"
    RF24_CRC_16: "rf24_crclength_e"

RF24_CRC_DISABLED: rf24_crclength_e = rf24_crclength_e.RF24_CRC_DISABLED
RF24_CRC_8: rf24_crclength_e = rf24_crclength_e.RF24_CRC_8
RF24_CRC_16: rf24_crclength_e = rf24_crclength_e.RF24_CRC_16

class rf24_datarate_e:
    RF24_1MBPS: rf24_datarate_e
    RF24_2MBPS: rf24_datarate_e
    RF24_250KBPS: rf24_datarate_e

RF24_1MBPS: rf24_datarate_e = rf24_datarate_e.RF24_1MBPS
RF24_2MBPS: rf24_datarate_e = rf24_datarate_e.RF24_2MBPS
RF24_250KBPS: rf24_datarate_e = rf24_datarate_e.RF24_250KBPS

class rf24_pa_dbm_e:
    RF24_PA_MIN: rf24_pa_dbm_e
    RF24_PA_LOW: rf24_pa_dbm_e
    RF24_PA_HIGH: rf24_pa_dbm_e
    RF24_PA_MAX: rf24_pa_dbm_e

RF24_PA_MIN: rf24_pa_dbm_e = rf24_pa_dbm_e.RF24_PA_MIN
RF24_PA_LOW: rf24_pa_dbm_e = rf24_pa_dbm_e.RF24_PA_LOW
RF24_PA_HIGH: rf24_pa_dbm_e = rf24_pa_dbm_e.RF24_PA_HIGH
RF24_PA_MAX: rf24_pa_dbm_e = rf24_pa_dbm_e.RF24_PA_MAX

class rf24_fifo_state_e:
    RF24_FIFO_OCCUPIED: rf24_fifo_state_e
    RF24_FIFO_EMPTY: rf24_fifo_state_e
    RF24_FIFO_FULL: rf24_fifo_state_e
    RF24_FIFO_INVALID: rf24_fifo_state_e

RF24_FIFO_OCCUPIED: rf24_fifo_state_e = rf24_fifo_state_e.RF24_FIFO_OCCUPIED
RF24_FIFO_EMPTY: rf24_fifo_state_e = rf24_fifo_state_e.RF24_FIFO_EMPTY
RF24_FIFO_FULL: rf24_fifo_state_e = rf24_fifo_state_e.RF24_FIFO_FULL
RF24_FIFO_INVALID: rf24_fifo_state_e = rf24_fifo_state_e.RF24_FIFO_INVALID

class RF24:
    @overload
    def __init__(
        self, ce_pin: int, csn_pin: int, spi_speed: int = 10000000
    ) -> None: ...
    @overload
    def __init__(self, spi_speed: int = 10000000) -> None: ...
    def available(self) -> bool: ...
    def available_pipe(self) -> Tuple[bool, int]: ...
    @overload
    def begin(self) -> bool: ...
    @overload
    def begin(
        self, ce_pin: Optional[int] = None, csn_pin: Optional[int] = None
    ) -> bool: ...
    def close_rx_pipe(self, pipe_number: int) -> None: ...
    def closeReadingPipe(self, pipe_number: int) -> None: ...
    def disableDynamicPayloads(self) -> None: ...
    def enableDynamicPayloads(self) -> None: ...
    def enable_dynamic_ack(self) -> None: ...
    def enableDynamicAck(self) -> None: ...
    def enableAckPayload(self) -> None: ...
    def flush_rx(self) -> None: ...
    def flush_tx(self) -> None: ...
    def get_arc(self) -> int: ...
    def getARC(self) -> int: ...
    def getChannel(self) -> int: ...
    def getCRCLength(self) -> rf24_crclength_e: ...
    def getDataRate(self) -> rf24_datarate_e: ...
    def get_dynamic_payload_size(self) -> int: ...
    def getDynamicPayloadSize(self) -> int: ...
    def getPALevel(self) -> int: ...
    def getPayloadSize(self) -> int: ...
    def isChipConnected(self) -> bool: ...
    def isPVariant(self) -> bool: ...
    def isValid(self) -> bool: ...
    @overload
    def is_fifo(self, about_tx: bool) -> rf24_fifo_state_e: ...
    @overload
    def is_fifo(self, about_tx: bool, check_empty: bool) -> bool: ...
    @overload
    def isFifo(self, about_tx: bool) -> rf24_fifo_state_e: ...
    @overload
    def isFifo(self, about_tx: bool, check_empty: bool) -> bool: ...
    def mask_irq(self, tx_ok: bool, tx_fail: bool, rx_ready: bool) -> None: ...
    def maskIRQ(self, tx_ok: bool, tx_fail: bool, rx_ready: bool) -> None: ...
    def open_tx_pipe(self, address: Union[bytes, bytearray, int]) -> None: ...
    def openWritingPipe(self, address: Union[bytes, bytearray, int]) -> None: ...
    def open_rx_pipe(
        self, number: int, address: Union[bytes, bytearray, int]
    ) -> None: ...
    def openReadingPipe(
        self, number: int, address: Union[bytes, bytearray, int]
    ) -> None: ...
    def powerUp(self) -> None: ...
    def powerDown(self) -> None: ...
    def print_details(self) -> None: ...
    def printDetails(self) -> None: ...
    def print_pretty_details(self) -> None: ...
    def printPrettyDetails(self) -> None: ...
    def read(self, length: int) -> bytearray: ...
    def reuse_tx(self) -> None: ...
    def reUseTX(self) -> None: ...
    def rxFifoFull(self) -> bool: ...
    def setAddressWidth(self, width: int) -> None: ...
    @overload
    def set_auto_ack(self, number: int, enable: bool) -> None: ...
    @overload
    def set_auto_ack(self, enable: bool) -> None: ...
    @overload
    def setAutoAck(self, number: int, enable: bool) -> None: ...
    @overload
    def setAutoAck(self, enable: bool) -> None: ...
    def setChannel(self, channel: int) -> None: ...
    def setCRCLength(self, length: rf24_crclength_e) -> None: ...
    def setDataRate(self, speed: rf24_datarate_e) -> None: ...
    def set_pa_level(self, level: rf24_pa_dbm_e, lna_enable: bool = True) -> None: ...
    def setPALevel(self, level: rf24_pa_dbm_e, lna_enable: bool = True) -> None: ...
    def set_retries(self, delay: int, count: int) -> None: ...
    def setRetries(self, delay: int, count: int) -> None: ...
    def set_radiation(
        self, level: rf24_pa_dbm_e, speed: rf24_datarate_e, lna_enable: bool = True
    ) -> None: ...
    def setRadiation(
        self, level: rf24_pa_dbm_e, speed: rf24_datarate_e, lna_enable: bool = True
    ) -> None: ...
    def setPayloadSize(self, size: int) -> None: ...
    def sprintf_pretty_details(self) -> str: ...
    def sprintfPrettyDetails(self) -> str: ...
    def startListening(self) -> None: ...
    def stopListening(self) -> None: ...
    def start_const_carrier(self, level: rf24_pa_dbm_e, channel: int) -> None: ...
    def startConstCarrier(self, level: rf24_pa_dbm_e, channel: int) -> None: ...
    def start_fast_write(
        self,
        buf: Union[bytearray, bytes],
        multicast: bool = False,
        start_tx: bool = True,
    ) -> None: ...
    def startFastWrite(
        self,
        buf: Union[bytearray, bytes],
        multicast: bool = False,
        start_tx: bool = True,
    ) -> None: ...
    def start_write(
        self, buf: Union[bytearray, bytes], multicast: bool = False
    ) -> bool: ...
    def startWrite(
        self, buf: Union[bytearray, bytes], multicast: bool = False
    ) -> bool: ...
    def stop_const_carrier(self) -> None: ...
    def stopConstCarrier(self) -> None: ...
    def testRPD(self) -> bool: ...
    def toggle_all_pipes(self, enable: bool) -> None: ...
    def toggleAllPipes(self, enable: bool) -> None: ...
    def tx_standby(
        self, timeout: Optional[int] = None, start_tx: bool = True
    ) -> bool: ...
    def txStandBy(
        self, timeout: Optional[int] = None, start_tx: bool = True
    ) -> bool: ...
    def what_happened(self) -> Tuple[bool, bool, bool]: ...
    def whatHappened(self) -> Tuple[bool, bool, bool]: ...
    def write(self, buf: Union[bytearray, bytes], multicast: bool = False) -> bool: ...
    def write_ack_payload(self, pipe: int, buf: Union[bytearray, bytes]) -> bool: ...
    def writeAckPayload(self, pipe: int, buf: Union[bytearray, bytes]) -> bool: ...
    def write_blocking(self, buf: Union[bytearray, bytes], timeout: int) -> bool: ...
    def writeBlocking(self, buf: Union[bytearray, bytes], timeout: int) -> bool: ...
    def write_fast(
        self, buf: Union[bytearray, bytes], multicast: bool = False
    ) -> bool: ...
    def writeFast(
        self, buf: Union[bytearray, bytes], multicast: bool = False
    ) -> bool: ...
    @property
    def ack_payloads(self) -> bool: ...
    @ack_payloads.setter
    def ack_payloads(self, enable: bool) -> None: ...
    @property
    def address_width(self) -> int: ...
    @address_width.setter
    def address_width(self, length: int) -> None: ...
    @property
    def channel(self) -> int: ...
    @channel.setter
    def channel(self, value: int) -> None: ...
    @property
    def crc_length(self) -> rf24_crclength_e: ...
    @crc_length.setter
    def crc_length(self, value: rf24_crclength_e) -> None: ...
    @property
    def tx_delay(self) -> int: ...
    @tx_delay.setter
    def tx_delay(self, value: int) -> None: ...
    @property
    def txDelay(self) -> int: ...
    @txDelay.setter
    def txDelay(self, value: int) -> None: ...
    @property
    def data_rate(self) -> int: ...
    @data_rate.setter
    def data_rate(self, value: rf24_datarate_e) -> None: ...
    @property
    def dynamic_payloads(self) -> bool: ...
    @dynamic_payloads.setter
    def dynamic_payloads(self, value: bool) -> None: ...
    @property
    def failure_detected(self) -> int: ...
    @failure_detected.setter
    def failure_detected(self, value: int) -> None: ...
    @property
    def failureDetected(self) -> int: ...
    @failureDetected.setter
    def failureDetected(self, value: int) -> None: ...
    @property
    def is_chip_connected(self) -> bool: ...
    @property
    def is_plus_variant(self) -> bool: ...
    @property
    def is_valid(self) -> bool: ...
    @property
    def listen(self) -> bool: ...
    @listen.setter
    def listen(self, is_rx: bool) -> None: ...
    @property
    def payload_size(self) -> int: ...
    @payload_size.setter
    def payload_size(self, length: int) -> None: ...
    @property
    def payloadSize(self) -> int: ...
    @payloadSize.setter
    def payloadSize(self, length: int) -> None: ...
    @property
    def pa_level(self) -> rf24_pa_dbm_e: ...
    @pa_level.setter
    def pa_level(self, level: rf24_pa_dbm_e) -> None: ...
    @property
    def power(self) -> bool: ...
    @power.setter
    def power(self, is_on: bool) -> None: ...
    @property
    def rpd(self) -> bool: ...
    @property
    def rx_fifo_full(self) -> bool: ...

######### stubs for RF24Network bindings ###########################################

MAX_USER_DEFINED_HEADER_TYPE: int = 127
MAX_PAYLOAD_SIZE: int = 1514
NETWORK_ADDR_RESPONSE: int = 128
NETWORK_PING: int = 130
EXTERNAL_DATA_TYPE: int = 131
NETWORK_FIRST_FRAGMENT: int = 148
NETWORK_MORE_FRAGMENTS: int = 149
NETWORK_LAST_FRAGMENT: int = 150
NETWORK_ACK: int = 193
NETWORK_POLL: int = 194
NETWORK_REQ_ADDRESS: int = 195
FLAG_FAST_FRAG: int = 4
FLAG_NO_POLL: int = 8

class RF24NetworkHeader:
    @overload
    def __init__(self, to_node: int, type: int = 0) -> None: ...
    @overload
    def __init__(self) -> None: ...
    def to_string(self) -> str: ...
    def toString(self) -> str: ...
    @property
    def to_node(self) -> int: ...
    @to_node.setter
    def to_node(self, value: int) -> None: ...
    @property
    def type(self) -> int: ...
    @type.setter
    def type(self, value: int) -> None: ...
    @property
    def id(self) -> int: ...
    @id.setter
    def id(self, value: int) -> None: ...
    @property
    def from_node(self) -> int: ...
    @from_node.setter
    def from_node(self, value: int) -> None: ...
    @property
    def reserved(self) -> int: ...
    @reserved.setter
    def reserved(self, value: int) -> None: ...
    @property
    def next_id(self) -> int: ...

# RF24NetworkFrame is not exposed as it is not needed
# class RF24NetworkFrame:
#     def __init__(
#         self, header: RF24NetworkHeader = None, message: Union[bytes, bytearray] = None
#     ) -> None: ...
#     @property
#     def header(self) -> RF24NetworkHeader: ...
#     @header.setter
#     def header(self, head: RF24NetworkHeader) -> None: ...
#     @property
#     def message_buffer(self) -> bytearray: ...
#     @message_buffer.setter
#     def message_buffer(self, message: Union[bytes, bytearray]) -> None: ...
#     @property
#     def message_size(self) -> int: ...

class RF24Network:
    def __init__(self, radio: RF24) -> None: ...
    @overload
    def begin(self, node_address: int) -> None: ...
    @overload
    def begin(self, channel: int, node_address: int) -> None: ...
    def is_address_valid(self, address: int) -> bool: ...
    def is_valid_address(self, address: int) -> bool: ...
    def multicast(
        self, header: RF24NetworkHeader, buf: Union[bytes, bytearray], level: int = 7
    ) -> bool: ...
    def multicastLevel(self, level: int) -> None: ...
    # @overload
    # def parent(self) -> int: ...
    @overload
    def peek(self, header: RF24NetworkHeader) -> int: ...
    @overload
    def peek(
        self, maxlen: int = MAX_PAYLOAD_SIZE
    ) -> Tuple[RF24NetworkHeader, bytearray]: ...
    def read(
        self, maxlen: int = MAX_PAYLOAD_SIZE
    ) -> Tuple[RF24NetworkHeader, bytearray]: ...
    def set_multicast_level(self, level: int) -> None: ...
    def update(self) -> int: ...
    def available(self) -> int: ...
    def write(
        self, header: RF24NetworkHeader, buf: Union[bytearray, bytes]
    ) -> bool: ...
    @property
    def multicast_relay(self) -> bool: ...
    @multicast_relay.setter
    def multicast_relay(self, enable: bool) -> None: ...
    @property
    def multicastRelay(self) -> bool: ...
    @multicastRelay.setter
    def multicastRelay(self, enable: bool) -> None: ...
    @property
    def multicast_level(self) -> int: ...
    @multicast_level.setter
    def multicast_level(self, level: int) -> None: ...
    @property
    def network_flags(self) -> int: ...
    @network_flags.setter
    def network_flags(self, flags: int) -> None: ...
    @property
    def networkFlags(self) -> int: ...
    @networkFlags.setter
    def networkFlags(self, flags: int) -> None: ...
    @property
    def node_address(self) -> int: ...
    @node_address.setter
    def node_address(self, address: int) -> None: ...
    @property
    def parent(self) -> int: ...
    @property
    def return_sys_msgs(self) -> bool: ...
    @return_sys_msgs.setter
    def return_sys_msgs(self, enable: bool) -> None: ...
    @property
    def returnSysMsgs(self) -> bool: ...
    @returnSysMsgs.setter
    def returnSysMsgs(self, enable: bool) -> None: ...
    @property
    def route_timeout(self) -> int: ...
    @route_timeout.setter
    def route_timeout(self, timeout: int) -> None: ...
    @property
    def routeTimeout(self) -> int: ...
    @routeTimeout.setter
    def routeTimeout(self, timeout: int) -> None: ...
    @property
    def tx_timeout(self) -> int: ...
    @tx_timeout.setter
    def tx_timeout(self, timeout: int) -> int: ...
    @property
    def txTimeout(self) -> int: ...
    @txTimeout.setter
    def txTimeout(self, timeout: int) -> int: ...
    # @property
    # def external_queue(self) -> List[RF24NetworkFrame]: ...

######### stubs for RF24Mesh bindings ###########################################

MESH_DEFAULT_ADDRESS: int = 0o4444
MESH_ADDR_LOOKUP: int = 196
MESH_ADDR_RELEASE: int = 197
MESH_ID_LOOKUP: int = 198

class AddrListStruct:
    def __init__(self): ...
    @property
    def node_id(self) -> int: ...
    @property
    def address(self) -> int: ...

class RF24Mesh:
    def __init__(self, radio: RF24, network: RF24Network) -> None: ...
    def begin(
        self,
        channel: int = 97,
        data_rate: rf24_datarate_e = rf24_datarate_e.RF24_1MBPS,
        timeout: int = 7500,
    ) -> bool: ...
    def check_connection(self) -> bool: ...
    def checkConnection(self) -> bool: ...
    def dhcp(self) -> None: ...
    def DHCP(self) -> None: ...
    def save_dhcp(self) -> None: ...
    def saveDHCP(self) -> None: ...
    def load_dhcp(self) -> None: ...
    def loadDHCP(self) -> None: ...
    def get_address(self, node_id: int) -> int: ...
    def getAddress(self, node_id: int) -> int: ...
    def set_address(
        self, node_id: int, address: int, search_by_address: bool = False
    ): ...
    def setAddress(
        self, node_id: int, address: int, search_by_address: bool = False
    ): ...
    def setStaticAddress(self, node_id: int, address: int) -> None: ...
    def set_node_id(self) -> None: ...
    def setNodeID(self) -> None: ...
    def get_node_id(self, address: int) -> int: ...
    def getNodeID(self, address: int) -> int: ...
    @overload
    def release_address(self) -> bool: ...
    @overload
    def release_address(self, address: int) -> bool: ...
    @overload
    def releaseAddress(self) -> bool: ...
    @overload
    def releaseAddress(self, address: int) -> bool: ...
    def renew_address(self, timeout: int = 7500) -> int: ...
    def renewAddress(self, timeout: int = 7500) -> int: ...
    def set_channel(self, channel: int) -> None: ...
    def setChannel(self, channel: int) -> None: ...
    def set_child(self, allow: bool) -> None: ...
    def setChild(self, allow: bool) -> None: ...
    def update(self) -> int: ...
    @overload
    def write(
        self, buf: Union[bytes, bytearray], message_type: int, to_node_id: int = 0
    ) -> bool: ...
    @overload
    def write(
        self, to_node: int, buf: Union[bytes, bytearray], message_type: int
    ) -> bool: ...
    @property
    def mesh_address(self) -> int: ...
    @property
    def node_id(self) -> int: ...
    @node_id.setter
    def node_id(self, number: int) -> None: ...
    @property
    def _nodeID(self) -> int: ...
    @_nodeID.setter
    def _nodeID(self, number: int) -> None: ...
    @property
    def addr_list(self) -> List[AddrListStruct]: ...
    @property
    def addrList(self) -> List[AddrListStruct]: ...
