from threading import Lock

from msgbus import MBEasyContext
from messagehandler import MessageHandlerBuilder, MessageHandler
from messageprocessor import MessageProcessorMessageHandler, LoggingProcessorCallback, \
    DefaultMessageProcessorExecutorFactory

from customer_services.interactor.update_customer import UpdateCustomerInteractor
from customer_services.service import GetCustomerService
from customer_services.interactor.add_customer import AddCustomerInteractor
from customer_services.interactor.get_customer import GetCustomerInteractor

from externals.processor import UpdateCustomerProcessor
from externals.repository.database import CustomerRepository
from externals.messages import ListenedMessages
from externals.processor import AddCustomerProcessor, GetCustomerProcessor
from externals.util import LoggerUtil, LogManager


database_lock = Lock()
logger = LoggerUtil.get_logger_name(__name__)


class ComponentMessageHandlerBuilder(MessageHandlerBuilder):
    def __init__(self, mb_context, persistence_name):
        # type: (MBEasyContext, str) -> None
        
        super(ComponentMessageHandlerBuilder, self).__init__()

        self.mb_context = mb_context
        self.persistence_name = persistence_name
        
        self.log_managers = None
        self.subject_counter = {}

    def build_singletons(self):
        # type: () -> None

        self.log_managers = LogManager("Subject Counter", self.subject_counter)
        self.log_managers.start()

    def build_message_handler(self):
        # type: () -> MessageHandler
        
        customer_repository = CustomerRepository(self.mb_context, self.persistence_name, database_lock)
        get_customer_service = GetCustomerService(customer_repository)

        add_customer = ListenedMessages.TK_CUSTOMER_ADD_CUSTOMER.value
        get_customer = ListenedMessages.TK_CUSTOMER_GET_CUSTOMER.value
        update_customer = ListenedMessages.TK_CUSTOMER_UPDATE_CUSTOMER.value
        
        add_customer_interactor = AddCustomerInteractor(customer_repository, get_customer_service)
        get_customer_interactor = GetCustomerInteractor(get_customer_service)
        update_customer_interactor = UpdateCustomerInteractor(customer_repository, get_customer_service)
        
        message_processors = {
                add_customer: AddCustomerProcessor(add_customer_interactor),
                get_customer: GetCustomerProcessor(get_customer_interactor),
                update_customer: UpdateCustomerProcessor(update_customer_interactor)
        }

        callbacks = [LoggingProcessorCallback(logger)]
        return MessageProcessorMessageHandler(None,
                                              message_processors,
                                              None,
                                              DefaultMessageProcessorExecutorFactory(callbacks=callbacks),
                                              subject_counter=self.subject_counter,
                                              logger=logger)

    def destroy_message_handler(self, message_handler):
        # type: (MessageHandlerBuilder) -> None
    
        return

    def destroy_singletons(self):
        # type: () -> None
        
        if self.log_managers:
            self.log_managers.stop()
