from service_locator_api.shared import error
from service_locator_api.shared.exception import (
    AddressChanged,
    RegistrationNotFound,
)
from service_locator_api.shared.token import TK_SERVICE_LOCATOR_ADDRESS_CHANGED
from messagebus import (
    AckMessage,
    Message,
    NakMessage,
    BadRequestMessage,
    ApplicationErrorMessage,
)
from messageprocessorutil import UuidMessageProcessor
from .. import KeepAliveError

from .._ServiceLocator import ServiceLocator


class KeepAliveProcessor(UuidMessageProcessor):

    def __init__(self, service_locator: ServiceLocator) -> None:
        super(KeepAliveProcessor, self).__init__()
        self.service_locator = service_locator

    def parse_data(self, data):
        try:
            return data.decode("utf-8")
        except UnicodeDecodeError:
            raise error.KeepAliveError.INVALID_REGISTRATION_ID

    def call_business(self, reg_id):
        # type: (str) -> None
        self.service_locator.keep_alive(reg_id)

    def format_response(self, message_bus, message, service_name, _):
        message_bus.reply_message(message, AckMessage())

    def format_exception(self, message_bus, message, input_obj, exception):
        if isinstance(exception, RegistrationNotFound):
            message_bus.reply_message(
                message=message,
                reply_message=ApplicationErrorMessage(
                    error_code=error.KeepAliveError.SUBSCRIPTION_ID_NOT_FOUND.code,
                    error_message=error.KeepAliveError.SUBSCRIPTION_ID_NOT_FOUND.message,
                )
            )
        elif isinstance(exception, AddressChanged):
            message_bus.reply_message(
                message=message,
                reply_message=Message(
                    token=TK_SERVICE_LOCATOR_ADDRESS_CHANGED,
                    data=exception.current_address.encode(),
                )
            )
        elif isinstance(exception, KeepAliveError):
            message_bus.reply_message(message, NakMessage(exception.message.encode("utf-8")))
        else:
            message_bus.reply_message(message, NakMessage(str(exception).encode("utf-8")))

    def format_parse_exception(self, message_bus, message, data, exception):
        if isinstance(exception, error.CodedError):
            message_bus.reply_message(
                message=message,
                reply_message=BadRequestMessage(
                    error_code=exception.code,
                    error_message=exception.message,
                )
            )
        else:
            message_bus.reply_message(message, NakMessage(str(exception).encode("utf-8")))
