from threading import Lock

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

from dailygoals_services.interactor.sales_challenge import GetSalesChallengeInteractor, InsertSalesChallengeInteractor,\
    DeleteSalesChallengeInteractor, UpdateSalesChallengeInteractor
from dailygoals_services.interactor.update_goals import UpdateGoalsInteractor
from dailygoals_services.interactor.update_total_sold import UpdateTotalSoldInteractor, UpdateTotalSoldOrderInteractor,\
    UpdateTotalSoldTableInteractor
from dailygoals_services.service import DailyGoalsService
from externals.processor import UpdateGoalsProcessor, UpdateTotalSoldProcessor, UpdateTotalSoldOrderProcessor,\
    UpdateTotalSoldTableProcessor, GetSalesChallengeProcessor, InsertSalesChallengeProcessor,\
    DeleteSalesChallengeProcessor, UpdateSalesChallengeProcessor
from externals.repository.database import DailyGoalsRepository
from externals.util import LoggerUtil, LogManager
from externals.messages import ListenedMessages, ListenedEvents

from old_helper import read_swconfig

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


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

        super(ComponentMessageHandlerBuilder, self).__init__()

        self.mb_context = mb_context
        self.persistence_name = persistence_name
        self.goals_filename = goals_filename
        self.store_id = None

        self.log_managers = None
        self.subject_counter = {}
        self.message_handler = None

    def set_store_id(self, store_id):
        self.store_id = store_id

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

        self.store_id = read_swconfig(self.mb_context, "Store.Id")
        self.log_managers = LogManager("Subject Counter", self.subject_counter)
        self.log_managers.start()

        daily_goals_repository = DailyGoalsRepository(self.mb_context, self.persistence_name, database_lock)

        daily_goals_service = DailyGoalsService(daily_goals_repository, self.mb_context)
        daily_goals_service.configure(self.store_id, self.goals_filename)

        update_goals = ListenedMessages.TK_DAILY_GOALS_UPDATE_GOALS.value
        update_total_sold = ListenedMessages.TK_DAILY_GOALS_UPDATE_TOTAL_SOLD.value
        get_sales_challenge = ListenedMessages.TK_DAILY_GOALS_GET_SALES_CHALLENGE.value
        insert_sales_challenge = ListenedMessages.TK_DAILY_GOALS_INSERT_SALES_CHALLENGE.value
        delete_sales_challenge = ListenedMessages.TK_DAILY_GOALS_DELETE_SALES_CHALLENGE.value
        update_sales_challenge = ListenedMessages.TK_DAILY_GOALS_UPDATE_SALES_CHALLENGE.value

        update_goals_interactor = UpdateGoalsInteractor(daily_goals_repository, daily_goals_service)
        update_total_sold_interactor = UpdateTotalSoldInteractor(daily_goals_repository, daily_goals_service)
        get_sales_challenge_interactor = GetSalesChallengeInteractor(daily_goals_repository)
        insert_sales_challenge_interactor = InsertSalesChallengeInteractor(daily_goals_repository)
        delete_sales_challenge_interactor = DeleteSalesChallengeInteractor(daily_goals_repository)
        update_sales_challenge_interactor = UpdateSalesChallengeInteractor(daily_goals_repository)

        message_processors = {
            update_goals: UpdateGoalsProcessor(update_goals_interactor),
            update_total_sold: UpdateTotalSoldProcessor(update_total_sold_interactor),
            get_sales_challenge: GetSalesChallengeProcessor(get_sales_challenge_interactor),
            insert_sales_challenge: InsertSalesChallengeProcessor(insert_sales_challenge_interactor),
            delete_sales_challenge: DeleteSalesChallengeProcessor(delete_sales_challenge_interactor),
            update_sales_challenge: UpdateSalesChallengeProcessor(update_sales_challenge_interactor)
        }

        order_modified = ListenedEvents.ORDER_MODIFIED.value
        table_closed = ListenedEvents.TABLE_CLOSED.value

        update_total_sold_from_order = UpdateTotalSoldOrderInteractor(daily_goals_repository, daily_goals_service)
        update_total_sold_from_table = UpdateTotalSoldTableInteractor(daily_goals_repository, daily_goals_service)

        event_processors = {
            order_modified: UpdateTotalSoldOrderProcessor(update_total_sold_from_order),
            table_closed: UpdateTotalSoldTableProcessor(update_total_sold_from_table)
        }

        callbacks = [LoggingProcessorCallback(logger)]
        self.message_handler = MessageProcessorMessageHandler(
            event_processors,
            message_processors,
            DefaultMessageProcessorExecutorFactory(callbacks)
        )

    def build_message_handler(self):
        # type: () -> MessageHandler
        return self.message_handler

    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()
