from abc import ABCMeta, abstractmethod
from logging import Logger

from cfgtools import Configuration
from dialogmanager import DialogManager
from messagebus import MessageBus, Message, DataType
from modelcommon.model import SitefResponse
from typing import (
    Any,
    Union
)

from model import (
    CancelPaymentOrderData,
    ConfirmFinishPaymentData,
    EftData,
    FinishPaymentData,
    PaymentResponse,
    StartPaymentData,
    TestConnectionData
)

TK_ACCOUNT_EFTACTIVITY = 0x00E00005


class PaymentProcessor(object):
    __metaclass__ = ABCMeta

    def __init__(self, message_bus, dialog_manager, config, logger):
        # type: (MessageBus, DialogManager, Configuration, Logger) -> None

        self.message_bus = message_bus
        self.dialog_manager = dialog_manager
        self.config = config
        self.logger = logger

    @abstractmethod
    def connection_status(self, test_connection_data):
        # type: (TestConnectionData) -> bool
        raise NotImplementedError()

    @abstractmethod
    def add_payment(self, start_payment_data):
        # type: (StartPaymentData) -> PaymentResponse
        raise NotImplementedError()

    @abstractmethod
    def cancel_payment_order(
        self,
        cancel_payment_order_data   # type: CancelPaymentOrderData
    ):
        # type: (...) -> Any[Union[SitefResponse, str]]

        raise NotImplementedError()

    @abstractmethod
    def cancel_payment(self):
        # type: () -> str
        raise NotImplementedError()

    @abstractmethod
    def finish_payment(
        self,
        finish_payment_data     # type: FinishPaymentData
    ):
        # type: (...) -> bool
        raise NotImplementedError()

    @abstractmethod
    def confirm_finish_payment(
        self,
        confirm_finish_payment_data     # type: ConfirmFinishPaymentData
    ):
        # type: (...) -> None
        raise NotImplementedError()

    @abstractmethod
    def get_name(self):
        # type: () -> str
        raise NotImplementedError()

    def stop(self):
        # type: () -> None
        pass

    def register_eft_activity(self, eft_data):
        # type: (EftData) -> None
        self.message_bus.send_message("account{}".format(eft_data.pos_id),
                                      Message(TK_ACCOUNT_EFTACTIVITY,
                                              DataType.param, eft_data.to_payload()))
