"""
Interfaces with Z-Wave sensors.

For more details about this platform, please refer to the documentation
https://home-assistant.io/components/binary_sensor.zwave/
"""
import logging
import datetime
import homeassistant.util.dt as dt_util
from homeassistant.helpers.event import track_point_in_time
from homeassistant.components import zwave
from homeassistant.components.zwave import workaround
from homeassistant.components.zwave import async_setup_platform  # noqa # pylint: disable=unused-import
from homeassistant.components.binary_sensor import (
    DOMAIN,
    BinarySensorDevice)

_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = []


def get_device(value, **kwargs):
    """Create zwave entity device."""
    device_mapping = workaround.get_device_mapping(value)
    if device_mapping == workaround.WORKAROUND_NO_OFF_EVENT:
        # Default the multiplier to 4
        re_arm_multiplier = (zwave.get_config_value(value.node, 9) or 4)
        return ZWaveTriggerSensor(value, "motion", re_arm_multiplier * 8)

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

    if value.command_class == zwave.const.COMMAND_CLASS_SENSOR_BINARY:
        return ZWaveBinarySensor(value, None)
    return None


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

    def __init__(self, value, device_class):
        """Initialize the sensor."""
        zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN)
        self._sensor_type = device_class
        self._state = self._value.data

    def update_properties(self):
        """Callback on data changes for node values."""
        self._state = self._value.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

    @property
    def should_poll(self):
        """No polling needed."""
        return False


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

    def __init__(self, value, device_class, re_arm_sec=60):
        """Initialize the sensor."""
        super(ZWaveTriggerSensor, self).__init__(value, device_class)
        self.re_arm_sec = re_arm_sec
        self.invalidate_after = None

    def update_properties(self):
        """Called when a value for this entity's node has changed."""
        self._state = self._value.data
        # 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())