"""The EHEIM autofeeder+ auto feeder."""

from __future__ import annotations

from logging import getLogger
from typing import TYPE_CHECKING, Any, override

from eheimdigital.device import EheimDigitalDevice
from eheimdigital.types import (
    EheimDigitalDataMissingError,
    FeederDataPacket,
    FeederDrumState,
    MsgTitle,
    UsrDtaPacket,
)

if TYPE_CHECKING:
    from eheimdigital.hub import EheimDigitalHub

_LOGGER = getLogger(__package__)


class EheimDigitalAutofeeder(EheimDigitalDevice):
    """EHEIM autofeeder+ auto feeder."""

    feeder_data: FeederDataPacket | None = None

    def __init__(self, hub: EheimDigitalHub, usrdta: UsrDtaPacket) -> None:
        """Initialize the EHEIM autofeeder+ auto feeder."""
        super().__init__(hub, usrdta)

    @override
    async def parse_message(self, msg: dict[str, Any]) -> None:
        """Parse a message."""
        if msg["title"] == MsgTitle.FEEDER_DATA:
            self.feeder_data = FeederDataPacket(**msg)

    @override
    async def update(self) -> None:
        """Get the new feeder state."""
        await self.hub.send_packet({
            "title": MsgTitle.GET_FEEDER_DATA,
            "to": self.mac_address,
            "from": "USER",
        })

    async def set_feeder_data(self, data: dict[str, Any]) -> None:
        """Send a SET_FEEDER_DATA packet, containing new values from data."""
        if self.feeder_data is None:
            _LOGGER.error("set_feeder_data: No FEEDER_DATA packet received yet.")
            return
        await self.hub.send_packet({
            "title": MsgTitle.SET_FEEDER_DATA,
            "to": self.mac_address,
            "from": "USER",
            "configuration": self.feeder_data["configuration"],
            "overfeeding": self.feeder_data["overfeeding"],
            "sync": self.feeder_data["sync"],
            "partnerName": self.feeder_data["partnerName"],
            "sollRegulation": self.feeder_data["sollRegulation"],
            "feedingBreak": self.feeder_data["feedingBreak"],
            "breakDay": self.feeder_data["breakDay"],
            **data,
        })

    async def set_feeder_full(self) -> None:
        """Set the feeder drum to full."""
        await self.hub.send_packet({
            "title": MsgTitle.SET_FEEDER_FULL,
            "to": self.mac_address,
            "from": "USER",
        })

    async def set_feeder_tara(self) -> None:
        """Set the current drum weight as tara."""
        await self.hub.send_packet({
            "title": MsgTitle.SET_FEEDER_TARA,
            "to": self.mac_address,
            "from": "USER",
        })

    async def manual_measurement(self) -> None:
        """Start a manual drum weight measurement."""
        await self.hub.send_packet({
            "title": MsgTitle.SET_MANUAL_MEASUREMENT,
            "to": self.mac_address,
            "from": "USER",
        })

    async def stop_feeder_sync(self) -> None:
        """Stop the feeder sync."""
        await self.hub.send_packet({
            "title": MsgTitle.SET_STOP_FEEDER_SYNC,
            "to": self.mac_address,
            "from": "USER",
        })

    @property
    def weight(self) -> float:
        """Get the weight of the feeder content in grams."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return self.feeder_data["weight"]

    @property
    def is_spinning(self) -> bool:
        """Get the spinning state of the feeder."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return bool(self.feeder_data["isSpinning"])

    @property
    def level(self) -> tuple[int, FeederDrumState]:
        """Get the level of the feeder drum."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return (
            self.feeder_data["level"][0],
            FeederDrumState(self.feeder_data["level"][1]),
        )

    @property
    def configuration(self) -> list[list[int]]:
        """Get the configuration of the feeder."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return self.feeder_data["configuration"]

    async def set_configuration(self, configuration: list[list[int]]) -> None:
        """Set the configuration of the feeder."""
        if self.feeder_data is None:
            return
        await self.set_feeder_data({
            "configuration": configuration,
        })

    @property
    def overfeeding(self) -> bool:
        """Get whether the overfeeding protection is enabled."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return bool(self.feeder_data["overfeeding"])

    async def set_overfeeding(self, *, overfeeding: bool) -> None:
        """Set the overfeeding protection."""
        if self.feeder_data is None:
            return
        await self.set_feeder_data({
            "overfeeding": int(overfeeding),
        })

    @property
    def sync(self) -> str:
        """Get the synced device address."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return self.feeder_data["sync"]

    async def set_sync(self, sync: str) -> None:
        """Set the synced device address."""
        if self.feeder_data is None:
            return
        await self.set_feeder_data({
            "sync": sync,
        })

    @property
    def partner_name(self) -> str:
        """Get the name of the synced device."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return self.feeder_data["partnerName"]

    async def set_partner_name(self, partner_name: str) -> None:
        """Set the name of the synced device."""
        if self.feeder_data is None:
            return
        await self.set_feeder_data({
            "partnerName": partner_name,
        })

    @property
    def soll_regulation(self) -> bool:
        """Get whether the filter speed regulation is enabled."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return bool(self.feeder_data["sollRegulation"])

    async def set_soll_regulation(self, *, soll_regulation: bool) -> None:
        """Set the filter speed regulation."""
        if self.feeder_data is None:
            return
        await self.set_feeder_data({
            "sollRegulation": int(soll_regulation),
        })

    @property
    def feeding_break(self) -> bool:
        """Get whether the random feeding break is enabled."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return bool(self.feeder_data["feedingBreak"])

    async def set_feeding_break(self, *, feeding_break: bool) -> None:
        """Set the random feeding break."""
        if self.feeder_data is None:
            return
        await self.set_feeder_data({
            "feedingBreak": int(feeding_break),
        })

    @property
    def break_day(self) -> bool:
        """Get whether today is a break day."""
        if self.feeder_data is None:
            raise EheimDigitalDataMissingError
        return bool(self.feeder_data["breakDay"])

    async def set_break_day(self, *, break_day: bool) -> None:
        """Set today as a break day."""
        if self.feeder_data is None:
            return
        await self.set_feeder_data({
            "breakDay": int(break_day),
        })

    @override
    def as_dict(self) -> dict[str, Any]:
        """Return the device as a dictionary."""
        return {
            "feeder_data": self.feeder_data,
            **super().as_dict(),
        }

    @property
    @override
    def is_missing_data(self) -> bool:
        return self.feeder_data is None
