from cfgtools import Group
from messagehandler import MessageHandlerBuilder
from messageprocessor import (
    DefaultMessageProcessorExecutorFactory,
    MessageProcessorMessageHandler,
)
from messageprocessorutil import LoggingProcessorCallback
from store_config.processor import (
    GetConfigProcessor,
    GetFullConfigProcessor,
    SetConfigProcessor,
    GetStoreConfigProcessor,
    UpdateStoreConfigProcessor,
)
from store_config_api.shared.token import (
    TK_STORE_CFG_GET,
    TK_STORE_CFG_GET_FULL,
    TK_STORE_CFG_SET,
    TK_STORE_CFG_GET_COMPLETE_CONFIG,
    TK_STORE_CFG_UPDATE_COMPLETE_CONFIG,
)
from .config import Config
from ..interactor import (
    GetStoreConfigInteractor,
    UpdateStoreConfigInteractor,
)
from ..repository import StoreConfigurationRepository
from ..service import StoreConfigurationService


class StoreConfigMessageHandlerBuilder(MessageHandlerBuilder):

    def __init__(self, config: Config):

        self.config = config
        self.config_dict = {}
        for key, value in read_config_recursively(self.config.store_config.find_group("PublishedConfiguration")):
            self.config_dict[key] = value

        self.get_store_config_processor = None
        self.update_store_config_processor = None

    def build_singletons(self):
        store_configuration_repository = StoreConfigurationRepository(
            configs=self.config_dict,
        )
        store_config_service = StoreConfigurationService(
            store_config_repository=store_configuration_repository,
        )

        get_store_config_interactor = GetStoreConfigInteractor(
            store_config_service=store_config_service,
        )
        self.get_store_config_processor = GetStoreConfigProcessor(
            interactor=get_store_config_interactor,
        )
        update_store_config_interactor = UpdateStoreConfigInteractor(
            store_config_service=store_config_service,
        )
        self.update_store_config_processor = UpdateStoreConfigProcessor(
            interactor=update_store_config_interactor,
        )

    def build_message_handler(self, message, event):
        return MessageProcessorMessageHandler(
            event_processors=None,
            message_processors={
                TK_STORE_CFG_GET_COMPLETE_CONFIG: self.get_store_config_processor,
                TK_STORE_CFG_UPDATE_COMPLETE_CONFIG: self.update_store_config_processor,
                TK_STORE_CFG_GET: GetConfigProcessor(config_dict=self.config_dict),
                TK_STORE_CFG_SET: SetConfigProcessor(config_dict=self.config_dict),
                TK_STORE_CFG_GET_FULL: GetFullConfigProcessor(store_config=self.config.store_config),
            },
            executor_factory=DefaultMessageProcessorExecutorFactory(
                [
                    LoggingProcessorCallback(),
                ]
            ),
        )

    def destroy_message_handler(self, message_handler):
        return

    def destroy_singletons(self):
        return


def read_config_recursively(group: Group, parent_path: str = ""):
    if len(group.keys) > 0:
        for key in group.keys:
            value = key.values if len(key.values) != 1 else key.values[0]
            full_key = f"{parent_path}.{key.name}" if parent_path else key.name
            yield full_key, value

    for child_group in group.groups:
        path = child_group.name
        if parent_path != "":
            path = f"{parent_path}.{child_group.name}"

        for key, value in read_config_recursively(group=child_group, parent_path=path):
            yield key, value
