import zmq

from typing import Optional
from logging import Logger
from messagebus import MessageBus
from zeromqmessagehandler._PublishEventWorkerThread import PublishEventWorkerThread
from zeromqthreadpool import ZeroMqPushPullThreadPool, ThreadPoolParameters


class PublisherMessageBus(MessageBus):
    def __init__(self, context, pub_address, logger, thread_pool_parameters=None):
        # type: (zmq.Context, str, Logger, Optional[ThreadPoolParameters]) -> None
        self.context = context
        self.pub_address = pub_address
        self.thread_pool_parameters = thread_pool_parameters

        if self.thread_pool_parameters is None:
            self.thread_pool_parameters = ThreadPoolParameters(5, 50, 5, 2000, 2000)
        self.push_address = "inproc://publisherPullAddress"
        self.thread_pool = ZeroMqPushPullThreadPool(
            self.context,
            self.push_address,
            self.thread_pool_parameters,
            "inproc://publisherWorkerAddress",
            logger,
            PublishEventWorkerThread,
            pub_address)

    def publish_event(self, event):
        type_data = event.event_type.encode("utf-8") if event.event_type is not None else b""
        event_data = b"" if event.data is None else event.data
        data = event.subject.encode("utf-8") + b" " + type_data + b"\0" + event_data

        pub_socket = self.context.socket(zmq.PUSH)
        pub_socket.connect(self.push_address)
        pub_socket.send(data)
        pub_socket.close()

    def send_message(self, component, message):
        pass

    def subscribe(self, subject):
        pass

    def reply_message(self, message, reply_message):
        pass

    def reply_event(self, event, reply_message):
        pass

    def get_thread_pool_count(self):
        return self.thread_pool.get_current_thread_count()
