"""
Platform for Lutron switches.

Provides switch functionality for Home Assistant.
"""
import logging

from homeassistant.components.switch import SwitchEntity, DOMAIN
from homeassistant.const import CONF_DEVICES, CONF_HOST, CONF_MAC, CONF_NAME, CONF_ID

from . import (
    Caseta,
    ATTR_AREA_NAME,
    CONF_AREA_NAME,
    ATTR_INTEGRATION_ID,
    DOMAIN as COMPONENT_DOMAIN,
)

_LOGGER = logging.getLogger(__name__)


class CasetaData:
    """Data holder for a switch."""

    def __init__(self, caseta):
        """Initialize the data holder."""
        self._caseta = caseta
        self._devices = []

    @property
    def devices(self):
        """Return the device list."""
        return self._devices

    @property
    def caseta(self):
        """Return a reference to Casetify instance."""
        return self._caseta

    def set_devices(self, devices):
        """Set the device list."""
        self._devices = devices

    async def read_output(self, mode, integration, action, value):
        """Receive output value from the bridge."""
        # find integration ID in devices
        if mode == Caseta.OUTPUT:
            for device in self._devices:
                if device.integration == integration:
                    _LOGGER.debug(
                        "Got switch OUTPUT value: %s %d %d %f",
                        mode,
                        integration,
                        action,
                        value,
                    )
                    if action == Caseta.Action.SET:
                        device.update_state(value)
                        if device.hass is not None:
                            await device.async_update_ha_state()
                        break


# pylint: disable=unused-argument
async def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Configure the platform."""
    if discovery_info is None:
        return
    bridge = Caseta(discovery_info[CONF_HOST])
    await bridge.open()

    data = CasetaData(bridge)
    devices = [
        CasetaSwitch(switch, data, discovery_info[CONF_MAC])
        for switch in discovery_info[CONF_DEVICES]
    ]
    data.set_devices(devices)

    async_add_devices(devices, True)

    # register callbacks
    bridge.register(data.read_output)

    # start bridge main loop
    bridge.start(hass)


class CasetaSwitch(SwitchEntity):
    """Representation of a Lutron switch."""

    def __init__(self, switch, data, mac):
        """Initialize a Lutron switch."""
        self._data = data
        self._name = switch[CONF_NAME]
        self._area_name = None
        if CONF_AREA_NAME in switch:
            self._area_name = switch[CONF_AREA_NAME]
            # if available, prepend area name to switch
            self._name = switch[CONF_AREA_NAME] + " " + switch[CONF_NAME]
        self._integration = int(switch[CONF_ID])
        self._is_on = False
        self._mac = mac

    async def async_added_to_hass(self):
        """Update initial state."""
        await self.query()

    async def query(self):
        """Query the bridge for the current level."""
        await self._data.caseta.query(
            Caseta.OUTPUT, self._integration, Caseta.Action.SET
        )

    @property
    def integration(self):
        """Return the Integration ID."""
        return self._integration

    @property
    def unique_id(self) -> str:
        """Return a unique ID."""
        if self._mac is not None:
            return "{}_{}_{}_{}".format(
                COMPONENT_DOMAIN, DOMAIN, self._mac, self._integration
            )
        return None

    @property
    def name(self):
        """Return the display name of this switch."""
        return self._name

    @property
    def device_state_attributes(self):
        """Return device specific state attributes."""
        attr = {ATTR_INTEGRATION_ID: self._integration}
        if self._area_name:
            attr[ATTR_AREA_NAME] = self._area_name
        return attr

    @property
    def is_on(self):
        """Return true if switch is on."""
        return self._is_on

    async def async_turn_on(self, **kwargs):
        """Instruct the switch to turn on."""
        _LOGGER.debug(
            "Writing switch OUTPUT value: %d %d 100",
            self._integration,
            Caseta.Action.SET,
        )
        await self._data.caseta.write(
            Caseta.OUTPUT, self._integration, Caseta.Action.SET, 100
        )

    async def async_turn_off(self, **kwargs):
        """Instruct the switch to turn off."""
        _LOGGER.debug(
            "Writing switch OUTPUT value: %d %d 0", self._integration, Caseta.Action.SET
        )
        await self._data.caseta.write(
            Caseta.OUTPUT, self._integration, Caseta.Action.SET, 0
        )

    def update_state(self, value):
        """Update state."""
        self._is_on = value > 0