import typing

from enum import IntEnum, StrEnum

import zmq


# types
JSONSerializable = typing.Union[str, int, float, bool, None, typing.Dict[str, typing.Any], typing.List]
JSON = typing.Dict[str, JSONSerializable]

byte_types = (bytes, bytearray, memoryview)

# decorator constants
# naming
USE_OBJECT_NAME: str = "USE_OBJECT_NAME"
# state machine
ANY_STATE: str = "ANY_STATE"
UNSPECIFIED: str = "UNSPECIFIED"
# types


class ResourceTypes(StrEnum):
    """Exposed resource types"""

    PROPERTY = "PROPERTY"
    ACTION = "ACTION"
    EVENT = "EVENT"
    THING = "THING"


class REGEX(StrEnum):
    """common regexes"""

    states = "[A-Za-z_]+[A-Za-z_ 0-9]*"
    url = r"[\-a-zA-Z0-9@:%._\/\+~#=]{1,256}"


class HTTP_METHODS(StrEnum):
    """currently supported HTTP request methods"""

    GET = "GET"
    POST = "POST"
    PUT = "PUT"
    DELETE = "DELETE"
    PATCH = "PATCH"
    # OPTIONS = 'OPTIONS'


class ZMQ_TRANSPORTS(StrEnum):
    """
    supported ZMQ transport protocols - TCP, IPC, INPROC

    TCP - needs socket address additional specified like tcp://0.0.0.0:{port}
    IPC - within python, multiprocess applications, can be autogenerated
    INPROC - within python, multithreaded applications, can be autogenerated
    """

    TCP = "TCP"
    IPC = "IPC"
    INPROC = "INPROC"


class ZMQSocketType(IntEnum):
    """General ZMQ socket types"""

    PAIR = zmq.PAIR
    PUB = zmq.PUB
    SUB = zmq.SUB
    REQ = zmq.REQ
    REP = zmq.REP
    DEALER = zmq.DEALER
    ROUTER = zmq.ROUTER
    PULL = zmq.PULL
    PUSH = zmq.PUSH
    XPUB = zmq.XPUB
    XSUB = zmq.XSUB
    STREAM = zmq.STREAM
    # Add more socket types as needed


ZMQ_EVENT_MAP = {}
"""Built-in ZMQ events"""

for name in dir(zmq):
    if name.startswith("EVENT_"):
        value = getattr(zmq, name)
        ZMQ_EVENT_MAP[value] = name


class Operations(StrEnum):
    """WoT operations (both standard and non-standard)"""

    readproperty = "readproperty"
    writeproperty = "writeproperty"
    deleteproperty = "deleteproperty"
    observeproperty = "observeproperty"

    readmultipleproperties = "readmultipleproperties"
    writemultipleproperties = "writemultipleproperties"
    readallproperties = "readallproperties"
    writeallproperties = "writeallproperties"

    invokeaction = "invokeaction"
    subscribeevent = "subscribeevent"
    unsubscribevent = "unsubscribevent"


__all__ = [HTTP_METHODS.__name__, ZMQ_TRANSPORTS.__name__, Operations.__name__]
