import threading

from source import packets, structures
from source.behaviors import events
from source.utils.dict import TimestampedDict


class Manager:
    """
    Global manager
    """

    def __init__(self, interface: str):
        from . import CommunicationManager, EventManager, RoleManager, AudioManager, PeerManager

        # communication manager
        self.communication = CommunicationManager(self, interface)
        self.communication.register_packet_type(b"DISC", packets.DiscoveryPacket)
        self.communication.register_packet_type(b"PEER", packets.PeerPacket)
        self.communication.register_packet_type(b"AUDI", packets.AudioPacket)
        self.communication.register_packet_type(b"RQSK", packets.RequestKeyPacket)
        self.communication.register_packet_type(b"GTSK", packets.KeyPacket)

        # event manager
        self.event = EventManager(self)
        self.event.register_event_handler(packets.DiscoveryPacket, events.DiscoveryEvent(self))
        self.event.register_event_handler(packets.PeerPacket, events.PeerEvent(self))
        self.event.register_event_handler(packets.AudioPacket, events.AudioEvent(self))
        self.event.register_event_handler(packets.RequestKeyPacket, events.RequestKeyEvent(self))
        self.event.register_event_handler(packets.KeyPacket, events.KeyEvent(self))

        # role manager
        self.role = RoleManager(self)

        # audio manager
        self.audio = AudioManager(self)

        # peer manager
        self.peer = PeerManager(self)

    def loop(self) -> None:
        """
        Handle the sub-managers forever
        """

        # run a thread for the event and the role manager
        event_thread = threading.Thread(target=self.event.loop)
        role_thread = threading.Thread(target=self.role.loop)
        audio_thread = threading.Thread(target=self.audio.loop)
        peer_thread = threading.Thread(target=self.peer.loop)

        event_thread.start()
        role_thread.start()
        audio_thread.start()
        peer_thread.start()

        event_thread.join()
        role_thread.join()
        audio_thread.join()
        peer_thread.join()
