from typing import Dict

from messagebus import (
    MessageBus,
    SubscriptionInfo,
)
from ._EventPublishDetail import EventPublishDetail
from ._EventRepositoryFactory import EventRepositoryFactory
from ._NewEventListener import NewEventListener


class AsyncTargetReplySubscriber(NewEventListener):
    def __init__(
        self,
        message_bus: MessageBus,
        event_repository_factory: EventRepositoryFactory,
    ):
        self.message_bus = message_bus

        self.subscriptions: Dict[str, bool] = {}
        with event_repository_factory.build() as event_repository:
            pending_events = event_repository.get_pending()
            for pending_event in pending_events:
                if pending_event.async_target is None:
                    continue

                self._subscribe(reply_subject=pending_event.async_target.reply_subject)

    def new_event(self, publish_detail: EventPublishDetail):
        if not publish_detail.has_async_target():
            return

        self._subscribe(reply_subject=publish_detail.async_target.reply_subject)

    def _subscribe(self, reply_subject: str):
        if reply_subject in self.subscriptions:
            return

        self.message_bus.subscribe(
            [
                SubscriptionInfo(
                    subject=reply_subject,
                    subscription_type=SubscriptionInfo.TYPE_NON_REENTRANT,
                ),
            ]
        )
        self.subscriptions[reply_subject] = True
