"""Support for Tahoma cover - shutters etc."""
from datetime import timedelta
import logging

from homeassistant.components.cover import (
    ATTR_POSITION,
    DEVICE_CLASS_AWNING,
    DEVICE_CLASS_BLIND,
    DEVICE_CLASS_CURTAIN,
    DEVICE_CLASS_GARAGE,
    DEVICE_CLASS_SHUTTER,
    DEVICE_CLASS_WINDOW,
    CoverEntity,
)
from homeassistant.util.dt import utcnow

from . import DOMAIN as TAHOMA_DOMAIN, TahomaDevice

_LOGGER = logging.getLogger(__name__)

ATTR_MEM_POS = "memorized_position"
ATTR_RSSI_LEVEL = "rssi_level"
ATTR_LOCK_START_TS = "lock_start_ts"
ATTR_LOCK_END_TS = "lock_end_ts"
ATTR_LOCK_LEVEL = "lock_level"
ATTR_LOCK_ORIG = "lock_originator"

HORIZONTAL_AWNING = "io:HorizontalAwningIOComponent"

TAHOMA_DEVICE_CLASSES = {
    HORIZONTAL_AWNING: DEVICE_CLASS_AWNING,
    "io:AwningValanceIOComponent": DEVICE_CLASS_AWNING,
    "io:DiscreteGarageOpenerWithPartialPositionIOComponent": DEVICE_CLASS_GARAGE,
    "io:DiscreteGarageOpenerIOComponent": DEVICE_CLASS_GARAGE,
    "io:ExteriorVenetianBlindIOComponent": DEVICE_CLASS_BLIND,
    "io:GarageOpenerIOComponent": DEVICE_CLASS_GARAGE,
    "io:RollerShutterGenericIOComponent": DEVICE_CLASS_SHUTTER,
    "io:RollerShutterUnoIOComponent": DEVICE_CLASS_SHUTTER,
    "io:RollerShutterVeluxIOComponent": DEVICE_CLASS_SHUTTER,
    "io:RollerShutterWithLowSpeedManagementIOComponent": DEVICE_CLASS_SHUTTER,
    "io:VerticalExteriorAwningIOComponent": DEVICE_CLASS_AWNING,
    "io:VerticalInteriorBlindVeluxIOComponent": DEVICE_CLASS_BLIND,
    "io:WindowOpenerVeluxIOComponent": DEVICE_CLASS_WINDOW,
    "rts:BlindRTSComponent": DEVICE_CLASS_BLIND,
    "rts:CurtainRTSComponent": DEVICE_CLASS_CURTAIN,
    "rts:DualCurtainRTSComponent": DEVICE_CLASS_CURTAIN,
    "rts:ExteriorVenetianBlindRTSComponent": DEVICE_CLASS_BLIND,
    "rts:RollerShutterRTSComponent": DEVICE_CLASS_SHUTTER,
    "rts:VenetianBlindRTSComponent": DEVICE_CLASS_BLIND,
}


def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the Tahoma covers."""
    if discovery_info is None:
        return
    controller = hass.data[TAHOMA_DOMAIN]["controller"]
    devices = []
    for device in hass.data[TAHOMA_DOMAIN]["devices"]["cover"]:
        devices.append(TahomaCover(device, controller))
    add_entities(devices, True)


class TahomaCover(TahomaDevice, CoverEntity):
    """Representation a Tahoma Cover."""

    def __init__(self, tahoma_device, controller):
        """Initialize the device."""
        super().__init__(tahoma_device, controller)

        self._closure = 0
        # 100 equals open
        self._position = 100
        self._closed = False
        self._rssi_level = None
        self._icon = None
        # Can be 0 and bigger
        self._lock_timer = 0
        self._lock_start_ts = None
        self._lock_end_ts = None
        # Can be 'comfortLevel1', 'comfortLevel2', 'comfortLevel3',
        # 'comfortLevel4', 'environmentProtection', 'humanProtection',
        # 'userLevel1', 'userLevel2'
        self._lock_level = None
        # Can be 'LSC', 'SAAC', 'SFC', 'UPS', 'externalGateway', 'localUser',
        # 'myself', 'rain', 'security', 'temperature', 'timer', 'user', 'wind'
        self._lock_originator = None

    def update(self):
        """Update method."""
        self.controller.get_states([self.tahoma_device])

        # For vertical covers
        self._closure = self.tahoma_device.active_states.get("core:ClosureState")
        # For horizontal covers
        if self._closure is None:
            self._closure = self.tahoma_device.active_states.get("core:DeploymentState")

        # For all, if available
        if "core:PriorityLockTimerState" in self.tahoma_device.active_states:
            old_lock_timer = self._lock_timer
            self._lock_timer = self.tahoma_device.active_states[
                "core:PriorityLockTimerState"
            ]
            # Derive timestamps from _lock_timer, only if not already set or
            # something has changed
            if self._lock_timer > 0:
                _LOGGER.debug("Update %s, lock_timer: %d", self._name, self._lock_timer)
                if self._lock_start_ts is None:
                    self._lock_start_ts = utcnow()
                if self._lock_end_ts is None or old_lock_timer != self._lock_timer:
                    self._lock_end_ts = utcnow() + timedelta(seconds=self._lock_timer)
            else:
                self._lock_start_ts = None
                self._lock_end_ts = None
        else:
            self._lock_timer = 0
            self._lock_start_ts = None
            self._lock_end_ts = None

        self._lock_level = self.tahoma_device.active_states.get(
            "io:PriorityLockLevelState"
        )

        self._lock_originator = self.tahoma_device.active_states.get(
            "io:PriorityLockOriginatorState"
        )

        self._rssi_level = self.tahoma_device.active_states.get("core:RSSILevelState")

        # Define which icon to use
        if self._lock_timer > 0:
            if self._lock_originator == "wind":
                self._icon = "mdi:weather-windy"
            else:
                self._icon = "mdi:lock-alert"
        else:
            self._icon = None

        # Define current position.
        #   _position: 0 is closed, 100 is fully open.
        #   'core:ClosureState': 100 is closed, 0 is fully open.
        if self._closure is not None:
            if self.tahoma_device.type == HORIZONTAL_AWNING:
                self._position = self._closure
            else:
                self._position = 100 - self._closure
            if self._position <= 5:
                self._position = 0
            if self._position >= 95:
                self._position = 100
            self._closed = self._position == 0
        else:
            self._position = None
            if "core:OpenClosedState" in self.tahoma_device.active_states:
                self._closed = (
                    self.tahoma_device.active_states["core:OpenClosedState"] == "closed"
                )
            if "core:OpenClosedPartialState" in self.tahoma_device.active_states:
                self._closed = (
                    self.tahoma_device.active_states["core:OpenClosedPartialState"]
                    == "closed"
                )
            else:
                self._closed = False

        _LOGGER.debug("Update %s, position: %d", self._name, self._position)

    @property
    def current_cover_position(self):
        """Return current position of cover."""
        return self._position

    def set_cover_position(self, **kwargs):
        """Move the cover to a specific position."""
        if self.tahoma_device.type == "io:WindowOpenerVeluxIOComponent":
            command = "setClosure"
        else:
            command = "setPosition"

        if self.tahoma_device.type == HORIZONTAL_AWNING:
            self.apply_action(command, kwargs.get(ATTR_POSITION, 0))
        else:
            self.apply_action(command, 100 - kwargs.get(ATTR_POSITION, 0))

    @property
    def is_closed(self):
        """Return if the cover is closed."""
        return self._closed

    @property
    def device_class(self):
        """Return the class of the device."""
        return TAHOMA_DEVICE_CLASSES.get(self.tahoma_device.type)

    @property
    def device_state_attributes(self):
        """Return the device state attributes."""
        attr = {}
        super_attr = super().device_state_attributes
        if super_attr is not None:
            attr.update(super_attr)

        if "core:Memorized1PositionState" in self.tahoma_device.active_states:
            attr[ATTR_MEM_POS] = self.tahoma_device.active_states[
                "core:Memorized1PositionState"
            ]
        if self._rssi_level is not None:
            attr[ATTR_RSSI_LEVEL] = self._rssi_level
        if self._lock_start_ts is not None:
            attr[ATTR_LOCK_START_TS] = self._lock_start_ts.isoformat()
        if self._lock_end_ts is not None:
            attr[ATTR_LOCK_END_TS] = self._lock_end_ts.isoformat()
        if self._lock_level is not None:
            attr[ATTR_LOCK_LEVEL] = self._lock_level
        if self._lock_originator is not None:
            attr[ATTR_LOCK_ORIG] = self._lock_originator
        return attr

    @property
    def icon(self):
        """Return the icon to use in the frontend, if any."""
        return self._icon

    def open_cover(self, **kwargs):
        """Open the cover."""
        self.apply_action("open")

    def close_cover(self, **kwargs):
        """Close the cover."""
        self.apply_action("close")

    def stop_cover(self, **kwargs):
        """Stop the cover."""
        if (
            self.tahoma_device.type
            == "io:RollerShutterWithLowSpeedManagementIOComponent"
        ):
            self.apply_action("setPosition", "secured")
        elif self.tahoma_device.type in {
            "io:ExteriorVenetianBlindIOComponent",
            "rts:BlindRTSComponent",
            "rts:DualCurtainRTSComponent",
            "rts:ExteriorVenetianBlindRTSComponent",
            "rts:VenetianBlindRTSComponent",
        }:
            self.apply_action("my")
        elif self.tahoma_device.type in {
            HORIZONTAL_AWNING,
            "io:AwningValanceIOComponent",
            "io:RollerShutterGenericIOComponent",
            "io:VerticalExteriorAwningIOComponent",
            "io:VerticalInteriorBlindVeluxIOComponent",
            "io:WindowOpenerVeluxIOComponent",
        }:
            self.apply_action("stop")
        else:
            self.apply_action("stopIdentify")
