from abc import ABCMeta, abstractmethod
from typing import Optional, Union, Callable, List

from twisted.internet.defer import Deferred

from vortex.PayloadEnvelope import VortexMsgList

SendVortexMsgResponseCallable = Callable[
    [Union[VortexMsgList, bytes], int], Deferred
]


class VortexInfo:
    """Vortex Info

    This class stores details about the end of a vortex.
    """

    def __init__(self, name, uuid):
        self.name, self.uuid = name, uuid

    def __repr__(self):
        return "VortexInfo, Name=%s, UUID=%s" % (self.name, self.uuid)


class VortexABC(metaclass=ABCMeta):
    @property
    @abstractmethod
    def localVortexInfo(self) -> VortexInfo:
        pass

    @property
    @abstractmethod
    def remoteVortexInfo(self) -> List[VortexInfo]:
        pass

    @property
    @abstractmethod
    def requiresBase64Encoding(self) -> bool:
        pass

    @abstractmethod
    def sendVortexMsg(
        self,
        vortexMsgs: Union[VortexMsgList, bytes],
        vortexUuid: Optional[str] = None,
    ):
        """Send Vortex Msg

        Sends the vortex message to any conencted clients with vortexUuid.
        Or broadcast it to all connected vortex clients if it's None

        :param vortexMsgs: The vortex message(s) to send
        :param vortexUuid: The vortexUuid of the client to send to.
        """
