# -*- coding: utf-8 -*-
from dialogmanager import DialogManager
from messagehandler import MessageHandlerBuilder
from messagepaymentprocessor import (
    CancelPaymentProcessor,
    CancelPaymentOrderProcessor,
    ConfirmFinishPaymentProcessor,
    FinishPaymentProcessor,
    GetDocumentProcessor,
    GetElectronicTypesProcessor,
    TestConnectionProcessor,
    StartPaymentProcessor,
    GetNameProcessor,
    CacheProcessor,
)
from messageprocessor import (
    DefaultMessageProcessorExecutorFactory,
    MessageProcessorMessageHandler,
)
from messageprocessorutil import LoggingProcessorCallback
from messagetoken import MessageToken
from paymentrouter import PaymentRouter
from typing import Optional
from util import Cache


class ElectronicPaymentMessageHandlerBuilder(MessageHandlerBuilder):
    def __init__(self, message_bus, config, logger):
        self.message_bus = message_bus
        self.config = config
        self.logger = logger

        self.message_handler = None
        self.dialog_manager = None  # type: Optional[DialogManager]
        self.payment_router = None  # type: Optional[PaymentRouter]
        self.cache = None           # type: Optional[Cache]

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

        self.dialog_manager = DialogManager(
            message_bus=self.message_bus,
            logger=self.logger,
        )

        self.cache = Cache(
            message_bus=self.message_bus,
            dialog_manager=self.dialog_manager,
            logger=self.logger,
        )

        self.payment_router = PaymentRouter(
            message_bus=self.message_bus,
            dialog_manager=self.dialog_manager,
            config=self.config,
            logger=self.logger,
            cache=self.cache,
        )

    def build_message_handler(self, _, __):
        event_processors = {}
        message_processors = {
            MessageToken.TK_ELECTRONIC_PAYMENT_ADD_PAYMENT: StartPaymentProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_CANCEL_PAYMENT: CancelPaymentProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_CANCEL_PAYMENT_ORDER: CancelPaymentOrderProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_FINISH_PAYMENT: FinishPaymentProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_CONFIRM_FINISH: ConfirmFinishPaymentProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_CONNECTIVITY_TEST: TestConnectionProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_GET_ELECTRONIC_TYPES: GetElectronicTypesProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_GET_DOCUMENT: GetDocumentProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_GET_NAME: GetNameProcessor(self.payment_router),
            MessageToken.TK_ELECTRONIC_PAYMENT_SEND_RESPONSE: self.dialog_manager,
            MessageToken.TK_ELECTRONIC_PAYMENT_CACHE: CacheProcessor(
                payment_router=self.payment_router,
                cache=self.cache,
            ),
        }
        self.message_handler = MessageProcessorMessageHandler(
            event_processors,
            message_processors,
            DefaultMessageProcessorExecutorFactory([LoggingProcessorCallback(self.logger)]),
            None
        )
        return self.message_handler

    def destroy_message_handler(self, message_handler):
        pass  # no special handling necessary to destroy message handlers

    def destroy_singletons(self):
        self.payment_router.stop_processors()
