import logging
from abc import ABCMeta
from typing import Optional

from messagebus import LowLevelMessageBus
from messagehandler import (
    MessageHandlerBuilder,
    MessageHandlerExecutor,
)
from ._HandleMessageStrategy import HandleMessageStrategy
from ._MessageReceiver import MessageReceiver

logger = logging.getLogger(__name__)


class MultiStrategyMessageReceiver(MessageReceiver):
    __metaclass__ = ABCMeta

    def __init__(
        self,                           # type: MultiStrategyMessageReceiver
        message_bus,                    # type: LowLevelMessageBus
        message_handler_builder,        # type: MessageHandlerBuilder
        poll_timeout,                   # type: Optional[int]
        handle_strategy,                # type: HandleMessageStrategy
    ):
        self.message_bus = message_bus
        self.message_handler_builder = message_handler_builder
        self.poll_timeout = poll_timeout
        self.handle_strategy = handle_strategy

        self.running = True

    def receive_messages(
        self,       # type: MultiStrategyMessageReceiver
    ):
        with MessageHandlerExecutor(
            message_bus=self.message_bus,
            message_handler_builder=self.message_handler_builder,
        ) as executor:      # type: MessageHandlerExecutor
            while self.running:
                try:
                    message = self.message_bus.receive(timeout=self.poll_timeout)
                    if message is None:
                        continue

                    self.handle_strategy.handle_message(
                        executor=executor,
                        message=message,
                    )
                except (Exception,):
                    logger.exception("Error handling message")

    def stop(self):
        self.running = False
