from abc import abstractmethod

from messagebus import (
    Message,
    MessageBus,
    DefaultToken,
    DataType,
    InternalErrorMessage,
)
from messageprocessorutil import UuidMessageProcessor
from typing import (
    Any,
    Optional,
    List,
)

from devicemanager.interactor.dto import DeviceStatusDto
from ._DeviceStatusFormatter import DeviceStatusFormatter


class DeviceStatusDtoProcessor(UuidMessageProcessor):

    @abstractmethod
    def parse_data(self, data, event_type):
        raise NotImplementedError()

    @abstractmethod
    def call_business(self, obj):
        raise NotImplementedError()

    def format_response(
        self,           # type: DeviceStatusDtoProcessor
        message_bus,    # type: MessageBus
        message,        # type: Message
        event,          # type: Optional[Any]
        request,        # type: Any
        result,         # type: List[DeviceStatusDto]
    ):
        # type: (...) -> None

        reply_message = Message(
            token=DefaultToken.TK_SYS_ACK,
            data_type=DataType.json,
            data=DeviceStatusFormatter.format_as_json(devices=result),
        )
        message_bus.reply_message(
            message=message,
            reply_message=reply_message,
        )

    def format_exception(
        self,           # type: DeviceStatusDtoProcessor
        message_bus,    # type: MessageBus
        message,        # type: Message
        event,          # type: Optional[Any]
        input_obj,      # type: Any
        exception,      # type: Exception
    ):
        # type: (...) -> None

        message_bus.reply_message(
            message=message,
            reply_message=InternalErrorMessage(ex=exception),
        )

    def format_parse_exception(
        self,           # type: DeviceStatusDtoProcessor
        message_bus,    # type: MessageBus
        message,        # type: Message
        event,          # type: Optional[Any]
        data,           # type: Any
        exception,      # type: Exception
    ):
        # type: (...) -> None

        return self.format_exception(
            message_bus=message_bus,
            message=message,
            event=event,
            input_obj=data,
            exception=exception,
        )
