"""
Support for Neato Connected Vaccums sensors.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.neato/
"""
import logging
import requests
from homeassistant.helpers.entity import Entity
from homeassistant.components.neato import (
    NEATO_ROBOTS, NEATO_LOGIN, NEATO_MAP_DATA, ACTION, ERRORS, MODE, ALERTS)

_LOGGER = logging.getLogger(__name__)

DEPENDENCIES = ['neato']

SENSOR_TYPE_STATUS = 'status'
SENSOR_TYPE_BATTERY = 'battery'

SENSOR_TYPES = {
    SENSOR_TYPE_STATUS: ['Status'],
    SENSOR_TYPE_BATTERY: ['Battery']
}

ATTR_CLEAN_START = 'clean_start'
ATTR_CLEAN_STOP = 'clean_stop'
ATTR_CLEAN_AREA = 'clean_area'
ATTR_CLEAN_BATTERY_START = 'battery_level_at_clean_start'
ATTR_CLEAN_BATTERY_END = 'battery_level_at_clean_end'
ATTR_CLEAN_SUSP_COUNT = 'clean_suspension_count'
ATTR_CLEAN_SUSP_TIME = 'clean_suspension_time'


def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the Neato sensor platform."""
    dev = []
    for robot in hass.data[NEATO_ROBOTS]:
        for type_name in SENSOR_TYPES:
            dev.append(NeatoConnectedSensor(hass, robot, type_name))
    _LOGGER.debug("Adding sensors %s", dev)
    add_devices(dev)


class NeatoConnectedSensor(Entity):
    """Neato Connected Sensor."""

    def __init__(self, hass, robot, sensor_type):
        """Initialize the Neato Connected sensor."""
        self.type = sensor_type
        self.robot = robot
        self.neato = hass.data[NEATO_LOGIN]
        self._robot_name = self.robot.name + ' ' + SENSOR_TYPES[self.type][0]
        self._status_state = None
        try:
            self._state = self.robot.state
        except (requests.exceptions.ConnectionError,
                requests.exceptions.HTTPError) as ex:
            self._state = None
            _LOGGER.warning("Neato connection error: %s", ex)
        self._mapdata = hass.data[NEATO_MAP_DATA]
        self.clean_time_start = None
        self.clean_time_stop = None
        self.clean_area = None
        self.clean_battery_start = None
        self.clean_battery_end = None
        self.clean_suspension_charge_count = None
        self.clean_suspension_time = None
        self._battery_state = None

    def update(self):
        """Update the properties of sensor."""
        _LOGGER.debug('Update of sensor')
        self.neato.update_robots()
        self._mapdata = self.hass.data[NEATO_MAP_DATA]
        try:
            self._state = self.robot.state
        except (requests.exceptions.ConnectionError,
                requests.exceptions.HTTPError) as ex:
            self._state = None
            self._status_state = 'Offline'
            _LOGGER.warning("Neato connection error: %s", ex)
            return
        if not self._state:
            return
        _LOGGER.debug('self._state=%s', self._state)
        if self.type == SENSOR_TYPE_STATUS:
            if self._state['state'] == 1:
                if self._state['details']['isCharging']:
                    self._status_state = 'Charging'
                elif (self._state['details']['isDocked'] and
                      not self._state['details']['isCharging']):
                    self._status_state = 'Docked'
                else:
                    self._status_state = 'Stopped'
            elif self._state['state'] == 2:
                if ALERTS.get(self._state['error']) is None:
                    self._status_state = (
                        MODE.get(self._state['cleaning']['mode'])
                        + ' ' + ACTION.get(self._state['action']))
                else:
                    self._status_state = ALERTS.get(self._state['error'])
            elif self._state['state'] == 3:
                self._status_state = 'Paused'
            elif self._state['state'] == 4:
                self._status_state = ERRORS.get(self._state['error'])
        if self.type == SENSOR_TYPE_BATTERY:
            self._battery_state = self._state['details']['charge']
        if not self._mapdata.get(self.robot.serial, {}).get('maps', []):
            return
        self.clean_time_start = (
            (self._mapdata[self.robot.serial]['maps'][0]['start_at']
             .strip('Z'))
            .replace('T', ' '))
        self.clean_time_stop = (
            (self._mapdata[self.robot.serial]['maps'][0]['end_at'].strip('Z'))
            .replace('T', ' '))
        self.clean_area = (
            self._mapdata[self.robot.serial]['maps'][0]['cleaned_area'])
        self.clean_suspension_charge_count = (
            self._mapdata[self.robot.serial]['maps'][0]
            ['suspended_cleaning_charging_count'])
        self.clean_suspension_time = (
            self._mapdata[self.robot.serial]['maps'][0]
            ['time_in_suspended_cleaning'])
        self.clean_battery_start = (
            self._mapdata[self.robot.serial]['maps'][0]['run_charge_at_start'])
        self.clean_battery_end = (
            self._mapdata[self.robot.serial]['maps'][0]['run_charge_at_end'])

    @property
    def unit_of_measurement(self):
        """Return unit for the sensor."""
        if self.type == SENSOR_TYPE_BATTERY:
            return '%'

    @property
    def available(self):
        """Return True if sensor data is available."""
        return self._state

    @property
    def state(self):
        """Return the sensor state."""
        if self.type == SENSOR_TYPE_STATUS:
            return self._status_state
        if self.type == SENSOR_TYPE_BATTERY:
            return self._battery_state

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._robot_name

    @property
    def device_state_attributes(self):
        """Return the device specific attributes."""
        data = {}
        if self.type is SENSOR_TYPE_STATUS:
            if self.clean_time_start:
                data[ATTR_CLEAN_START] = self.clean_time_start
            if self.clean_time_stop:
                data[ATTR_CLEAN_STOP] = self.clean_time_stop
            if self.clean_area:
                data[ATTR_CLEAN_AREA] = self.clean_area
            if self.clean_suspension_charge_count:
                data[ATTR_CLEAN_SUSP_COUNT] = (
                    self.clean_suspension_charge_count)
            if self.clean_suspension_time:
                data[ATTR_CLEAN_SUSP_TIME] = self.clean_suspension_time
            if self.clean_battery_start:
                data[ATTR_CLEAN_BATTERY_START] = self.clean_battery_start
            if self.clean_battery_end:
                data[ATTR_CLEAN_BATTERY_END] = self.clean_battery_end
        return data
