import cython

from .._sanitize cimport safe_label_str
from ..connection cimport APIConnection
from .base cimport (
    APIFrameHelper,
    _MAX_EXPLANATION_LEN,
    _MAX_MAC_LEN,
    _MAX_NAME_LEN,
)
from .noise_encryption cimport EncryptCipher, DecryptCipher

cdef bint TYPE_CHECKING


@cython.locals(
    type_="unsigned int",
    data=bytes,
    data_header=bytes,
    packet=tuple,
    data_len=Py_ssize_t,
    frame=bytes,
    frame_len=Py_ssize_t,
)
cpdef list make_noise_packets(list packets, EncryptCipher encrypt_cipher) except *

cdef unsigned int NOISE_STATE_HELLO
cdef unsigned int NOISE_STATE_HANDSHAKE
cdef unsigned int NOISE_STATE_READY
cdef unsigned int NOISE_STATE_CLOSED

cdef bytes NOISE_HELLO
cdef object InvalidTag
cdef object ESPHOME_NOISE_BACKEND

cdef class APINoiseFrameHelper(APIFrameHelper):

    cdef object _noise_psk
    cdef str _expected_name
    cdef str _expected_mac
    cdef unsigned int _state
    cdef str _server_mac
    cdef str _server_name
    cdef object _proto
    cdef EncryptCipher _encrypt_cipher
    cdef DecryptCipher _decrypt_cipher

    @cython.locals(
        header=bytes,
        preamble="unsigned char",
        header="const unsigned char *"
    )
    cpdef void data_received(self, object data) except *

    @cython.locals(
        msg=bytes,
        msg_type="unsigned int",
        payload=bytes,
        msg_length=Py_ssize_t,
        msg_cstr="const unsigned char *",
    )
    cdef void _handle_frame(self, bytes frame) except *

    @cython.locals(
        chosen_proto=char,
        server_name_i=int,
        mac_address_i=int,
        mac_address=str,
        mac_address_raw=str,
        server_name=str,
        server_name_raw=str,
    )
    cdef void _handle_hello(self, bytes server_hello) except *

    cdef void _handle_handshake(self, bytes msg) except *

    cdef void _handle_closed(self, bytes frame) except *

    @cython.locals(handshake_frame=bytearray, frame_len="unsigned int")
    cdef void _send_hello_handshake(self) except *

    cdef void _setup_proto(self) except *

    @cython.locals(psk_bytes=bytes)
    cdef _decode_noise_psk(self)

    cpdef void write_packets(self, list packets, bint debug_enabled) except *

    cdef _error_on_incorrect_preamble(self, bytes msg)
