"""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
