"""Support for Toon binary sensors."""

import logging
from typing import Any

from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.typing import HomeAssistantType

from . import (
    ToonData,
    ToonEntity,
    ToonDisplayDeviceEntity,
    ToonBoilerDeviceEntity,
    ToonBoilerModuleDeviceEntity,
)
from .const import DATA_TOON, DOMAIN

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(
        hass: HomeAssistantType, entry: ConfigEntry, async_add_entities
) -> None:
    """Set up a Toon binary sensor based on a config entry."""
    toon = hass.data[DATA_TOON][entry.entry_id]

    sensors = [
        ToonBoilerModuleBinarySensor(
            toon,
            'thermostat_info',
            'boiler_connected',
            None,
            'Boiler Module Connection',
            'mdi:check-network-outline',
            'connectivity',
        ),
        ToonDisplayBinarySensor(
            toon,
            'thermostat_info',
            'active_state',
            4,
            "Toon Holiday Mode",
            'mdi:airport',
            None,
        ),
        ToonDisplayBinarySensor(
            toon,
            'thermostat_info',
            'next_program',
            None,
            "Toon Program",
            'mdi:calendar-clock',
            None,
        ),
    ]

    if toon.thermostat_info.have_ot_boiler:
        sensors.extend(
            [
                ToonBoilerBinarySensor(
                    toon,
                    'thermostat_info',
                    'ot_communication_error',
                    '0',
                    "OpenTherm Connection",
                    'mdi:check-network-outline',
                    'connectivity',
                ),
                ToonBoilerBinarySensor(
                    toon,
                    'thermostat_info',
                    'error_found',
                    255,
                    "Boiler Status",
                    'mdi:alert',
                    'problem',
                    inverted=True,
                ),
                ToonBoilerBinarySensor(
                    toon,
                    'thermostat_info',
                    'burner_info',
                    None,
                    "Boiler Burner",
                    'mdi:fire',
                    None,
                ),
                ToonBoilerBinarySensor(
                    toon,
                    'thermostat_info',
                    'burner_info',
                    '2',
                    "Hot Tap Water",
                    'mdi:water-pump',
                    None,
                ),
                ToonBoilerBinarySensor(
                    toon,
                    'thermostat_info',
                    'burner_info',
                    '3',
                    "Boiler Preheating",
                    'mdi:fire',
                    None,
                ),
            ]
        )

    async_add_entities(sensors, True)


class ToonBinarySensor(ToonEntity, BinarySensorDevice):
    """Defines an Toon binary sensor."""

    def __init__(
            self,
            toon: ToonData,
            section: str,
            measurement: str,
            on_value: Any,
            name: str,
            icon: str,
            device_class: str,
            inverted: bool = False,
    ) -> None:
        """Initialize the Toon sensor."""
        self._state = inverted
        self._device_class = device_class
        self.section = section
        self.measurement = measurement
        self.on_value = on_value
        self.inverted = inverted

        super().__init__(toon, name, icon)

    @property
    def unique_id(self) -> str:
        """Return the unique ID for this binary sensor."""
        return '_'.join(
            [
                DOMAIN,
                self.toon.agreement.id,
                'binary_sensor',
                self.section,
                self.measurement,
                str(self.on_value),
            ]
        )

    @property
    def device_class(self) -> str:
        """Return the device class."""
        return self._device_class

    @property
    def is_on(self) -> bool:
        """Return the status of the binary sensor."""
        if self.on_value is not None:
            value = self._state == self.on_value
        elif self._state is None:
            value = False
        else:
            value = bool(max(0, int(self._state)))

        if self.inverted:
            return not value

        return value

    def update(self) -> None:
        """Get the latest data from the binary sensor."""
        section = getattr(self.toon, self.section)
        self._state = getattr(section, self.measurement)


class ToonBoilerBinarySensor(ToonBinarySensor, ToonBoilerDeviceEntity):
    """Defines a Boiler binary sensor."""

    pass


class ToonDisplayBinarySensor(ToonBinarySensor, ToonDisplayDeviceEntity):
    """Defines a Toon Display binary sensor."""

    pass


class ToonBoilerModuleBinarySensor(
        ToonBinarySensor, ToonBoilerModuleDeviceEntity
):
    """Defines a Boiler module binary sensor."""

    pass
