from service_locator_api.shared.error import CodedError, RegisterError
from messagebus import AckMessage, NakMessage, BadRequestMessage
from messageprocessorutil import UuidMessageProcessor
from .dto import RegisterServiceRequest

from .._ServiceLocator import ServiceLocator


class RegisterServiceProcessor(UuidMessageProcessor):

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

    def parse_data(self, data):
        if data == b"":
            raise RegisterError.EMPTY_SERVICE_NAME

        parts = data.split(b"\0")
        if len(parts) < 2:
            raise RegisterError.EMPTY_ADDRESS

        try:
            service_name = parts[0].decode("utf-8")
        except UnicodeDecodeError:
            raise RegisterError.INVALID_SERVICE_NAME

        try:
            service_address = parts[1].decode("utf-8")
        except UnicodeDecodeError:
            raise RegisterError.ADDRESS_CANNOT_BE_ENCODED_USING_UTF8

        return RegisterServiceRequest(service_name, service_address)

    def call_business(self, request):
        # type: (RegisterServiceRequest) -> None
        return self.service_locator.register_service(request.service_name, request.address)

    def format_response(self, message_bus, message, input_obj, reg_id):
        message_bus.reply_message(message, AckMessage(reg_id.encode("utf-8")))

    def format_exception(self, message_bus, message, input_obj, exception):
        message_bus.reply_message(message, NakMessage(str(exception).encode("utf-8")))

    def format_parse_exception(self, message_bus, message, data, exception):
        if isinstance(exception, 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")))
