from logging import Logger

from event_manager_api.shared.token import TK_EVENT_MANAGER_SUBSCRIBE
from messagehandler import MessageHandlerBuilder
from messageprocessor import MessageProcessorMessageHandler, DefaultMessageProcessorExecutorFactory
from messageprocessorutil import LoggingProcessorCallback
from zmq import Context

from zeromqeventmanager import (
    TK_EVENT_MANAGER_UNSUBSCRIBE,
    TK_EVENT_MANAGER_PUBLISH,
    TK_EVENT_MANAGER_KEEP_ALIVE,
    EventManager,
)
from zeromqeventmanager.processor import (
    SubscribeProcessor,
    PublishProcessor,
    KeepAliveProcessor,
)
from zeromqmessagehandler import ZeroMqMessageBus

from ._ConfigKey import ConfigKey


class EventManagerMessageHandlerBuilder(MessageHandlerBuilder):
    def __init__(self, context, config, message_bus, logger):
        # type: (Context, dict, ZeroMqMessageBus, Logger) -> None
        self.context = context
        self.config = config
        self.message_bus = message_bus
        self.logger = logger
        self.event_manager = None  # type: EventManager

    def build_singletons(self):
        self.event_manager = EventManager(
            context=self.context,
            message_bus=self.message_bus,
            pub_address=self.config.get(ConfigKey.PUB_ADDRESS),
            sub_address=self.config.get(ConfigKey.SUB_ADDRESS),
            pull_address=self.config.get(ConfigKey.PULL_ADDRESS),
            public_hostname=self.config.get(ConfigKey.PUBLIC_HOSTNAME),
            min_port=self.config.get(ConfigKey.MIN_STREAMER_PORT, 5001),
            max_port=self.config.get(ConfigKey.MAX_STREAMER_PORT, 5100),
            clean_interval=5,
            sub_id_lifetime=30,
            streamer_poll_timeout=self.config.get(ConfigKey.STREAMER_POLL_TIMEOUT, 1000)
        )

    def build_message_handler(self, message, event):
        handled_tokens = {
            TK_EVENT_MANAGER_SUBSCRIBE: SubscribeProcessor(self.event_manager),
            TK_EVENT_MANAGER_UNSUBSCRIBE: None,
            TK_EVENT_MANAGER_PUBLISH: PublishProcessor(self.event_manager),
            TK_EVENT_MANAGER_KEEP_ALIVE: KeepAliveProcessor(self.event_manager)
        }
        return MessageProcessorMessageHandler(
            None,
            handled_tokens,
            DefaultMessageProcessorExecutorFactory([LoggingProcessorCallback(self.logger)]))

    def destroy_message_handler(self, message_handler):
        pass

    def destroy_singletons(self):
        if self.event_manager is not None:
            self.event_manager.stop()
