"""Support for displaying the minimal and the maximal value."""
import logging

import voluptuous as vol

from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
    ATTR_UNIT_OF_MEASUREMENT,
    CONF_NAME,
    CONF_TYPE,
    STATE_UNAVAILABLE,
    STATE_UNKNOWN,
)
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_state_change

_LOGGER = logging.getLogger(__name__)

ATTR_MIN_VALUE = "min_value"
ATTR_MAX_VALUE = "max_value"
ATTR_COUNT_SENSORS = "count_sensors"
ATTR_MEAN = "mean"
ATTR_LAST = "last"

ATTR_TO_PROPERTY = [
    ATTR_COUNT_SENSORS,
    ATTR_MAX_VALUE,
    ATTR_MEAN,
    ATTR_MIN_VALUE,
    ATTR_LAST,
]

CONF_ENTITY_IDS = "entity_ids"
CONF_ROUND_DIGITS = "round_digits"

ICON = "mdi:calculator"

SENSOR_TYPES = {
    ATTR_MIN_VALUE: "min",
    ATTR_MAX_VALUE: "max",
    ATTR_MEAN: "mean",
    ATTR_LAST: "last",
}

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
    {
        vol.Optional(CONF_TYPE, default=SENSOR_TYPES[ATTR_MAX_VALUE]): vol.All(
            cv.string, vol.In(SENSOR_TYPES.values())
        ),
        vol.Optional(CONF_NAME): cv.string,
        vol.Required(CONF_ENTITY_IDS): cv.entity_ids,
        vol.Optional(CONF_ROUND_DIGITS, default=2): vol.Coerce(int),
    }
)


async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
    """Set up the min/max/mean sensor."""
    entity_ids = config.get(CONF_ENTITY_IDS)
    name = config.get(CONF_NAME)
    sensor_type = config.get(CONF_TYPE)
    round_digits = config.get(CONF_ROUND_DIGITS)

    async_add_entities(
        [MinMaxSensor(hass, entity_ids, name, sensor_type, round_digits)], True
    )
    return True


def calc_min(sensor_values):
    """Calculate min value, honoring unknown states."""
    val = None
    for sval in sensor_values:
        if sval != STATE_UNKNOWN:
            if val is None or val > sval:
                val = sval
    return val


def calc_max(sensor_values):
    """Calculate max value, honoring unknown states."""
    val = None
    for sval in sensor_values:
        if sval != STATE_UNKNOWN:
            if val is None or val < sval:
                val = sval
    return val


def calc_mean(sensor_values, round_digits):
    """Calculate mean value, honoring unknown states."""
    val = 0
    count = 0
    for sval in sensor_values:
        if sval != STATE_UNKNOWN:
            val += sval
            count += 1
    if count == 0:
        return None
    return round(val / count, round_digits)


class MinMaxSensor(Entity):
    """Representation of a min/max sensor."""

    def __init__(self, hass, entity_ids, name, sensor_type, round_digits):
        """Initialize the min/max sensor."""
        self._hass = hass
        self._entity_ids = entity_ids
        self._sensor_type = sensor_type
        self._round_digits = round_digits

        if name:
            self._name = name
        else:
            self._name = "{} sensor".format(
                next(v for k, v in SENSOR_TYPES.items() if self._sensor_type == v)