import os

from msgbus import MBEasyContext

from application.configurator import Configurator
from application.model import ListenedEvents, BenefitAppliers
from application.model.configuration import Configurations
from application.model.repository.benefit_applier import DefaultBenefitApplierRepository
from application.repository.pos import DBRepository
from application.repository.pos.benefitapplier import (
    LoyaltyCouponApplierRepository,
    NDiscountCouponApplierRepository,
)
from application.repository.pos.utils import fill_benefit_appliers_repositories
from helper import import_pydevd
from mbcontextmessagehandler import (
    MbContextMessageBus,
    MbContextMessageHandler,
)
from messagehandlerbuilder import ComponentMessageHandlerBuilder
from typing import Dict


def main():
    # type: () -> None

    loader_path = os.environ["LOADERCFG"]

    import_pydevd(loader_path, 9166)

    configurations = _get_configurations(loader_path)

    mb_context = MBEasyContext(configurations.service_name)
    message_bus = MbContextMessageBus(mb_context)

    db_repository = DBRepository(configurations, message_bus)
    benefit_appliers_repositories = _get_benefit_appliers_repositories(configurations, message_bus)

    component_message_handler_builder = ComponentMessageHandlerBuilder(configurations,
                                                                       db_repository,
                                                                       benefit_appliers_repositories)

    mb_context_message_handler = MbContextMessageHandler(message_bus,
                                                         configurations.service_name,
                                                         configurations.service_name,
                                                         configurations.required_services,
                                                         component_message_handler_builder)

    mb_context_message_handler.subscribe_reentrant_events([ListenedEvents.ORDER_MODIFIED.value])

    mb_context_message_handler.handle_events()


def _get_benefit_appliers_repositories(configs, message_bus):
    # type: (Configurations, MbContextMessageBus) -> Dict[BenefitAppliers: DefaultBenefitApplierRepository]

    benefit_appliers_repositories = {}
    default_params = [configs, message_bus]

    for benefit_applier in configs.supported_benefit_appliers:
        applier_name = benefit_applier.split("|")[0]
        if applier_name == BenefitAppliers.N_DISCOUNT:
            benefit_appliers_repositories[applier_name] = NDiscountCouponApplierRepository(*default_params)
        elif applier_name == BenefitAppliers.LOYALTY:
            benefit_appliers_repositories[applier_name] = LoyaltyCouponApplierRepository(*default_params)

    fill_benefit_appliers_repositories(benefit_appliers_repositories)

    return benefit_appliers_repositories


def _get_configurations(loader_path):
    # type: (str) -> Configurations

    configurator = Configurator(loader_path)

    configurator.read_loader_configurations()
    configurator.configure_logger()

    return configurator.configs


if __name__ == "__main__":
    main()
