import os

import cfgtools
from externals.events import ListenedReentrantEvents, ListenedNonReentrantEvents
from externals.message_handler_builder import HvMessageHandlerBuilder
from externals.tokens import ListenedQueueTokens
from helper import import_pydevd
from mbcontextmessagehandler import MbContextMessageBus, MbContextMessageHandler
from msgbus import MBEasyContext
from startup.common_main import configure_logger, COMPONENT_NAME
from typing import Dict, List


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

    loader_path = os.environ["LOADERCFG"]
    import_pydevd(loader_path, 9160)

    reader = cfgtools.read(loader_path)
    component_name = str(reader.find_value("Identification.ComponentName", default=COMPONENT_NAME))

    device_configurations = {key.name: key.value() if key.type != 1 else key.values
                             for key in reader.find_group("NPeripherals").keys}

    service_names = _get_service_names(device_configurations)

    logger = configure_logger(component_name, service_names[0])

    mb_context = MBEasyContext(component_name)

    message_bus = MbContextMessageBus(mb_context)

    hv_message_handler_builder = HvMessageHandlerBuilder(message_bus, device_configurations)
    message_handler = MbContextMessageHandler(message_bus, "", "", "", hv_message_handler_builder)

    mb_context.MB_EasyWaitStart()

    _register_services(component_name, mb_context, service_names)

    _register_non_reentrant_events(message_handler)

    _register_reentrant_events(message_handler)

    _register_queued_tokens(message_handler)

    logger.debug("Starting hv [{}][{}] ...".format(component_name, service_names))
    message_handler.handle_events()

    mb_context.MB_EasyFinalize()


def _register_non_reentrant_events(message_handler):
    listened_non_reentrant_events = ListenedNonReentrantEvents.list_names()
    if listened_non_reentrant_events:
        message_handler.subscribe_non_reentrant_events(listened_non_reentrant_events)


def _register_reentrant_events(message_handler):
    listened_reentrant_events = ListenedReentrantEvents.list_names()
    if listened_reentrant_events:
        message_handler.subscribe_reentrant_events(listened_reentrant_events)


def _register_queued_tokens(message_handler):
    listened_queue_tokens = ListenedQueueTokens.list_values()
    if listened_queue_tokens:
        message_handler.subscribe_queue_messages(listened_queue_tokens)


def _register_services(component_name, mb_context, service_names):
    for service in service_names:
        mb_context.MB_EasyRegisterService(component_name, service)


def _get_service_names(device_configurations):
    # type: (Dict[str, str]) -> List[str]
    service_names = device_configurations.get("Name", None)
    if not isinstance(service_names, list):
        return [service_names]
    return service_names


if __name__ == "__main__":
    main()
