"""Platform to control a Salda Smarty XP/XV ventilation unit."""
from __future__ import annotations

import logging
import math
from typing import Any

from pysmarty import Smarty

from homeassistant.components.fan import FanEntity, FanEntityFeature
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util.percentage import (
    int_states_in_range,
    percentage_to_ranged_value,
    ranged_value_to_percentage,
)

from . import DOMAIN, SIGNAL_UPDATE_SMARTY

_LOGGER = logging.getLogger(__name__)

DEFAULT_ON_PERCENTAGE = 66
SPEED_RANGE = (1, 3)  # off is not included


async def async_setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the Smarty Fan Platform."""
    smarty: Smarty = hass.data[DOMAIN]["api"]
    name: str = hass.data[DOMAIN]["name"]

    async_add_entities([SmartyFan(name, smarty)], True)


class SmartyFan(FanEntity):
    """Representation of a Smarty Fan."""

    _attr_icon = "mdi:air-conditioner"
    _attr_should_poll = False
    _attr_supported_features = FanEntityFeature.SET_SPEED

    def __init__(self, name, smarty):
        """Initialize the entity."""
        self._attr_name = name
        self._smarty_fan_speed = 0
        self._smarty = smarty

    @property
    def is_on(self) -> bool:
        """Return state of the fan."""
        return bool(self._smarty_fan_speed)

    @property
    def speed_count(self) -> int:
        """Return the number of speeds the fan supports."""
        return int_states_in_range(SPEED_RANGE)

    @property
    def percentage(self) -> int:
        """Return speed percentage of the fan."""
        if self._smarty_fan_speed == 0:
            return 0
        return ranged_value_to_percentage(SPEED_RANGE, self._smarty_fan_speed)

    def set_percentage(self, percentage: int) -> None:
        """Set the speed percentage of the fan."""
        _LOGGER.debug("Set the fan percentage to %s", percentage)
        if percentage == 0:
            self.turn_off()
            return

        fan_speed = math.ceil(percentage_to_ranged_value(SPEED_RANGE, percentage))
        if not self._smarty.set_fan_speed(fan_speed):
            raise HomeAssistantError(
                f"Failed to set the fan speed percentage to {percentage}"
            )

        self._smarty_fan_speed = fan_speed
        self.schedule_update_ha_state()

    def turn_on(
        self,
        percentage: int | None = None,
        preset_mode: str | None = None,
        **kwargs: Any,
    ) -> None:
        """Turn on the fan."""
        _LOGGER.debug("Turning on fan. percentage is %s", percentage)
        self.set_percentage(percentage or DEFAULT_ON_PERCENTAGE)

    def turn_off(self, **kwargs: Any) -> None:
        """Turn off the fan."""
        _LOGGER.debug("Turning off fan")
        if not self._smarty.turn_off():
            raise HomeAssistantError("Failed to turn off the fan")

        self._smarty_fan_speed = 0
        self.schedule_update_ha_state()

    async def async_added_to_hass(self) -> None:
        """Call to update fan."""
        self.async_on_remove(
            async_dispatcher_connect(
                self.hass, SIGNAL_UPDATE_SMARTY, self._update_callback
            )
        )

    @callback
    def _update_callback(self) -> None:
        """Call update method."""
        _LOGGER.debug("Updating state")
        self._smarty_fan_speed = self._smarty.fan_speed
        self.async_write_ha_state()