import json

from messagebus import (
    Event,
    Message,
    MessageBus,
)
from typing import (
    Any,
    Optional,
)

from devicemanager.interactor.dto import DeviceStatusDto
from devicemanager.interactor.update_devices_status import UpdateDevicesStatusInteractor
from devicemanager.interactor.update_devices_status.dto import (
    UpdateDevicesStatusRequest,
    UpdateDevicesStatusResponse,
)
from devicemanager.processor._DeviceStatusDtoProcessor import DeviceStatusDtoProcessor
from ._DeviceStatusFormatter import DeviceStatusFormatter


class UpdateDevicesStatusProcessor(DeviceStatusDtoProcessor):
    def __init__(
        self,
        update_devices_interactor,  # type: UpdateDevicesStatusInteractor
    ):
        # type: (...) -> None

        super(UpdateDevicesStatusProcessor, self).__init__()
        self.update_devices_interactor = update_devices_interactor

    def parse_data(
        self,           # type: UpdateDevicesStatusProcessor
        data,           # type: str
        event_type,     # type: str
    ):
        # type: (...) -> UpdateDevicesStatusRequest

        data = json.loads(data.decode("utf-8"))
        devices_json = data["devices"]
        devices = []
        for device in devices_json:
            devices.append(
                DeviceStatusDto(
                    type=device["deviceType"],
                    name=device["deviceName"],
                    enabled=device["enabled"],
                )
            )
        return UpdateDevicesStatusRequest(
            devices=devices,
            operator=data["operator"],
        )

    def call_business(
        self,                       # type: UpdateDevicesStatusProcessor
        update_devices_request,     # type: UpdateDevicesStatusRequest
    ):
        # type: (...) -> UpdateDevicesStatusResponse

        return self.update_devices_interactor.update_devices(request=update_devices_request)

    def format_response(
        self,           # type: UpdateDevicesStatusProcessor
        message_bus,    # type: MessageBus
        message,        # type: Message
        event,          # type: Optional[Any]
        request,        # type: Any
        result,         # type: UpdateDevicesStatusResponse
    ):

        if result.updated:
            update_event = Event(
                subject="DEVICE_STATUS_CHANGED",
                event_type="",
                data=DeviceStatusFormatter.format_as_json(devices=result.devices),
            )
            message_bus.publish_event(event=update_event)

        super(UpdateDevicesStatusProcessor, self).format_response(message_bus, message, event, request, result.devices)
