import logging
from datetime import datetime

from messagebus import (
    MessageBus,
)

from devicemanager.model import DeviceStatusHistory
from devicemanager.repository import DeviceManagerRepository
from devicemanager.service import (
    GetDevicesService,
    DeviceStatusService,
)
from .dto import (
    UpdateDevicesStatusRequest,
    UpdateDevicesStatusResponse,
)

logger = logging.getLogger(__name__)


class UpdateDevicesStatusInteractor(object):
    def __init__(
        self,
        repository,             # type: DeviceManagerRepository
        get_devices_service,    # type: GetDevicesService
        device_status_service,  # type: DeviceStatusService
        message_bus,            # type: MessageBus
    ):
        # type: (...) -> None

        self.repository = repository
        self.get_devices_service = get_devices_service
        self.device_status_service = device_status_service
        self.message_bus = message_bus

    def update_devices(
        self,     # type: UpdateDevicesStatusInteractor
        request,  # type: UpdateDevicesStatusRequest
    ):
        # type: (...) -> UpdateDevicesStatusResponse

        change_date = datetime.utcnow()
        device_names_to_remove = []
        device_names_to_add = []
        disabled_devices = self.repository.get_disabled_devices()
        for device in request.devices:
            if device.enabled and device.name in disabled_devices:
                device_names_to_remove.append(device.name)
            elif not device.enabled and device.name not in disabled_devices:
                device_names_to_add.append(device.name)

        updated = False
        for device_name in device_names_to_add:
            logger.info("Turning off {}".format(device_name))
            self.repository.create_device_status(device_name=device_name)
            self._create_status_history(
                device_name=device_name,
                change_date=change_date,
                operator=request.operator,
                enabled=False,
            )
            updated = True
        for device_name in device_names_to_remove:
            logger.info("Turning on {}".format(device_name))
            self.repository.delete_device_status(device_name=device_name)
            self._create_status_history(
                device_name=device_name,
                change_date=change_date,
                operator=request.operator,
                enabled=True,
            )
            updated = True

        devices = self.get_devices_service.get_devices()
        self.device_status_service.initialize_cache(repository=self.repository)
        return UpdateDevicesStatusResponse(
            updated=updated,
            devices=devices,
        )

    def _create_status_history(
        self,           # type: UpdateDevicesStatusInteractor
        device_name,    # type: str
        change_date,    # type: datetime
        operator,       # type: str
        enabled,        # type: bool
    ):
        self.repository.create_device_status_history(
            device_name=device_name,
            device_status_history=DeviceStatusHistory(
                enabled=enabled,
                timestamp=change_date,
                operator=operator,
            ),
        )
