"""Support for Z-Wave binary sensors."""
import datetime
import logging

from homeassistant.components.binary_sensor import DOMAIN, BinarySensorEntity
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.event import track_point_in_time
import homeassistant.util.dt as dt_util

from . import ZWaveDeviceEntity, workaround
from .const import COMMAND_CLASS_SENSOR_BINARY

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass, config_entry, async_add_entities):
    """Set up Z-Wave binary sensors from Config Entry."""

    @callback
    def async_add_binary_sensor(binary_sensor):
        """Add Z-Wave  binary sensor."""
        async_add_entities([binary_sensor])

    async_dispatcher_connect(hass, "zwave_new_binary_sensor", async_add_binary_sensor)


def get_device(values, **kwargs):
    """Create Z-Wave entity device."""
    device_mapping = workaround.get_device_mapping(values.primary)
    if device_mapping == workaround.WORKAROUND_NO_OFF_EVENT:
        return ZWaveTriggerSensor(values, "motion")

    if workaround.get_device_component_mapping(values.primary) == DOMAIN:
        return ZWaveBinarySensor(values, None)

    if values.primary.command_class == COMMAND_CLASS_SENSOR_BINARY:
        return ZWaveBinarySensor(values, None)
    return None


class ZWaveBinarySensor(BinarySensorEntity, ZWaveDeviceEntity):
    """Representation of a binary sensor within Z-Wave."""

    def __init__(self, values, device_class):
        """Initialize the sensor."""
        ZWaveDeviceEntity.__init__(self, values, DOMAIN)
        self._sensor_type = device_class
        self._state = self.values.primary.data

    def update_properties(self):
        """Handle data changes for node values."""
        self._state = self.values.primary.data

    @property
    def is_on(self):
        """Return true if the binary sensor is on."""
        return self._state

    @property
    def device_class(self):
        """Return the class of this sensor, from DEVICE_CLASSES."""
        return self._sensor_type


class ZWaveTriggerSensor(ZWaveBinarySensor):
    """Representation of a stateless sensor within Z-Wave."""

    def __init__(self, values, device_class):
        """Initialize the sensor."""
        super().__init__(values, device_class)
        # Set default off delay to 60 sec
        self.re_arm_sec = 60
        self.invalidate_after = None

    def update_properties(self):
        """Handle value changes for this entity's node."""
        self._state = self.values.primary.data
        _LOGGER.debug("off_delay=%s", self.values.off_delay)
        # Set re_arm_sec if off_delay is provided from the sensor
        if self.values.off_delay:
            _LOGGER.debug("off_delay.data=%s", self.values.off_delay.data)
            self.re_arm_sec = self.values.off_delay.data * 8
        # only allow this value to be true for re_arm secs
        if not self.hass:
            return

        self.invalidate_after = dt_util.utcnow() + datetime.timedelta(
            seconds=self.re_arm_sec
        )
        track_point_in_time(
            self.hass, self.async_update_ha_state, self.invalidate_after
        )

    @property
    def is_on(self):
        """Return true if movement has happened within the rearm time."""
        return self._state and (
            self.invalidate_after is None or self.invalidate_after > dt_util.utcnow()
        )