"""Support for Ecobee Thermostats."""
import logging

import voluptuous as vol

from homeassistant.components import ecobee
from homeassistant.components.climate import ClimateDevice
from homeassistant.components.climate.const import (
    DOMAIN, STATE_COOL, STATE_HEAT, STATE_AUTO, STATE_IDLE,
    ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, SUPPORT_TARGET_TEMPERATURE,
    SUPPORT_AWAY_MODE, SUPPORT_HOLD_MODE, SUPPORT_OPERATION_MODE,
    SUPPORT_TARGET_HUMIDITY_LOW, SUPPORT_TARGET_HUMIDITY_HIGH,
    SUPPORT_AUX_HEAT, SUPPORT_TARGET_TEMPERATURE_HIGH, SUPPORT_FAN_MODE,
    SUPPORT_TARGET_TEMPERATURE_LOW)
from homeassistant.const import (
    ATTR_ENTITY_ID, STATE_ON, STATE_OFF, ATTR_TEMPERATURE, TEMP_FAHRENHEIT)
import homeassistant.helpers.config_validation as cv

_CONFIGURING = {}
_LOGGER = logging.getLogger(__name__)

ATTR_FAN_MIN_ON_TIME = 'fan_min_on_time'
ATTR_RESUME_ALL = 'resume_all'

DEFAULT_RESUME_ALL = False
TEMPERATURE_HOLD = 'temp'
VACATION_HOLD = 'vacation'
AWAY_MODE = 'awayMode'

SERVICE_SET_FAN_MIN_ON_TIME = 'ecobee_set_fan_min_on_time'
SERVICE_RESUME_PROGRAM = 'ecobee_resume_program'

SET_FAN_MIN_ON_TIME_SCHEMA = vol.Schema({
    vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
    vol.Required(ATTR_FAN_MIN_ON_TIME): vol.Coerce(int),
})

RESUME_PROGRAM_SCHEMA = vol.Schema({
    vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
    vol.Optional(ATTR_RESUME_ALL, default=DEFAULT_RESUME_ALL): cv.boolean,
})

SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_AWAY_MODE |
                 SUPPORT_HOLD_MODE | SUPPORT_OPERATION_MODE |
                 SUPPORT_TARGET_HUMIDITY_LOW | SUPPORT_TARGET_HUMIDITY_HIGH |
                 SUPPORT_AUX_HEAT | SUPPORT_TARGET_TEMPERATURE_HIGH |
                 SUPPORT_TARGET_TEMPERATURE_LOW | SUPPORT_FAN_MODE)


def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the Ecobee Thermostat Platform."""
    if discovery_info is None:
        return
    data = ecobee.NETWORK
    hold_temp = discovery_info['hold_temp']
    _LOGGER.info(
        "Loading ecobee thermostat component with hold_temp set to %s",
        hold_temp)
    devices = [Thermostat(data, index, hold_temp)
               for index in range(len(data.ecobee.thermostats))]
    add_entities(devices)

    def fan_min_on_time_set_service(service):
        """Set the minimum fan on time on the target thermostats."""
        entity_id = service.data.get(ATTR_ENTITY_ID)
        fan_min_on_time = service.data[ATTR_FAN_MIN_ON_TIME]

        if entity_id:
            target_thermostats = [device for device in devices
                                  if device.entity_id in entity_id]
        else:
            target_thermostats = devices

        for thermostat in target_thermostats:
            thermostat.set_fan_min_on_time(str(fan_min_on_time))

            thermostat.schedule_update_ha_state(True)

    def resume_program_set_service(service):
        """Resume the program on the target thermostats."""
        entity_id = service.data.get(ATTR_ENTITY_ID)
        resume_all = service.data.get(ATTR_RESUME_ALL)

        if entity_id:
            target_thermostats = [device for device in devices
                                  if device.entity_id in entity_id]
        else:
            target_thermostats = devices

        for thermostat in target_thermostats:
            thermostat.resume_program(resume_all)

            thermostat.schedule_update_ha_state(True)

    hass.services.register(
        DOMAIN, SERVICE_SET_FAN_MIN_ON_TIME, fan_min_on_time_set_service,
        schema=SET_FAN_MIN_ON_TIME_SCHEMA)

    hass.services.register(
        DOMAIN, SERVICE_RESUME_PROGRAM, resume_program_set_service,
        schema=RESUME_PROGRAM_SCHEMA)


class Thermostat(ClimateDevice):
    """A thermostat class for Ecobee."""

    def __init__(self, data, thermostat_index, hold_temp):
        """Initialize the thermostat."""
        self.data = data
        self.thermostat_index = thermostat_index
        self.thermostat = self.data.ecobee.get_thermostat(
            self.thermostat_index)
        self._name = self.thermostat['name']
        self.hold_temp = hold_temp
        self.vacation = None
        self._climate_list = self.climate_list
        self._operation_list = ['auto', 'auxHeatOnly', 'cool',
                                'heat', 'off']
        self._fan_list = ['auto', 'on']
        self.update_without_throttle = False

    def update(self):
        """Get the latest state from the thermostat."""
        if self.update_without_throttle:
            self.data.update(no_throttle=True)
            self.update_without_throttle = False
        else:
            self.data.update()

        self.thermostat = self.data.ecobee.get_thermostat(
            self.thermostat_index)

    @property
    def supported_features(self):
        """Return the list of supported features."""
        return SUPPORT_FLAGS

    @property
    def name(self):
        """Return the name of the Ecobee Thermostat."""
        return self.thermostat['name']

    @property
    def temperature_unit(self):
        """Return the unit of measurement."""
        return TEMP_FAHRENHEIT

    @property
    def current_temperature(self):
        """Return the current temperature."""
        return self.thermostat['runtime']['actualTemperature'] / 10.0

    @property
    def target_temperature_low(self):
        """Return the lower bound temperature we try to reach."""
        if self.current_operation == STATE_AUTO:
            return self.thermostat['runtime']['desiredHeat'] / 10.0
        return None

    @property
    def target_temperature_high(self):
        """Return the upper bound temperature we try to reach."""
        if self.current_operation == STATE_AUTO:
            return self.thermostat['runtime']['desiredCool'] / 10.0
        return None

    @property
    def target_temperature(self):
        """Return the temperature we try to reach."""
        if self.current_operation == STATE_AUTO:
            return None
        if self.current_operation == STATE_HEAT:
            return self.thermostat['runtime']['desiredHeat'] / 10.0
        if self.current_operation == STATE_COOL:
            return self.thermostat['runtime']['desiredCool'] / 10.0
        return None

    @property
    def fan(self):
        """Return the current fan status."""
        if 'fan' in self.thermostat['equipmentStatus']:
            return STATE_ON
        return STATE_OFF

    @property
    def current_fan_mode(self):
        """Return the fan setting."""
        return self.thermostat['runtime']['desiredFanMode']

    @property
    def current_hold_mode(self):
        """Return current hold mode."""
        mode = self._current_hold_mode
        return None if mode == AWAY_MODE else mode

    @property
    def fan_list(self):
        """Return the available fan modes."""
        return self._fan_list

    @property
    def _current_hold_mode(self):
        events = self.thermostat['events']
        for event in events:
            if event['running']:
                if event['type'] == 'hold':
                    if event['holdClimateRef'] == 'away':
                        if int(event['endDate'][0:4]) - \
                                int(event['startDate'][0:4]) <= 1:
                            # A temporary hold from away climate is a hold
                            return 'away'
                        # A permanent hold from away climate
                        return AWAY_MODE
                    if event['holdClimateRef'] != "":
                        # Any other hold based on climate
                        return event['holdClimateRef']
                    # Any hold not based on a climate is a temp hold
                    return TEMPERATURE_HOLD
                if event['type'].startswith('auto'):
                    # All auto modes are treated as holds
                    return event['type'][4:].lower()
                if event['type'] == 'vacation':
                    self.vacation = event['name']
                    return VACATION_HOLD
        return None

    @property
    def current_operation(self):
        """Return current operation."""
        if self.operation_mode == 'auxHeatOnly' or \
                self.operation_mode == 'heatPump':
            return STATE_HEAT
        return self.operation_mode

    @property