"""Helpers to deal with bayesian observations."""
from __future__ import annotations

from dataclasses import dataclass, field
import uuid

from homeassistant.const import (
    CONF_ABOVE,
    CONF_BELOW,
    CONF_ENTITY_ID,
    CONF_PLATFORM,
    CONF_VALUE_TEMPLATE,
)
from homeassistant.helpers.template import Template

from .const import CONF_P_GIVEN_F, CONF_P_GIVEN_T, CONF_TO_STATE


@dataclass
class Observation:
    """Representation of a sensor or template observation.

    Either entity_id or value_template should be non-None.
    """

    entity_id: str | None
    platform: str
    prob_given_true: float
    prob_given_false: float
    to_state: str | None
    above: float | None
    below: float | None
    value_template: Template | None
    observed: bool | None = None
    id: uuid.UUID = field(default_factory=uuid.uuid4)

    def to_dict(self) -> dict[str, str | float | bool | None]:
        """Represent Class as a Dict for easier serialization."""

        # Needed because dataclasses asdict() can't serialize Templates and ignores Properties.
        dic = {
            CONF_PLATFORM: self.platform,
            CONF_ENTITY_ID: self.entity_id,
            CONF_VALUE_TEMPLATE: self.template,
            CONF_TO_STATE: self.to_state,
            CONF_ABOVE: self.above,
            CONF_BELOW: self.below,
            CONF_P_GIVEN_T: self.prob_given_true,
            CONF_P_GIVEN_F: self.prob_given_false,
            "observed": self.observed,
        }

        for key, value in dic.copy().items():
            if value is None:
                del dic[key]

        return dic

    def is_mirror(self, other: Observation) -> bool:
        """Dectects whether given observation is a mirror of this one."""
        return (
            self.platform == other.platform
            and round(self.prob_given_true + other.prob_given_true, 1) == 1
            and round(self.prob_given_false + other.prob_given_false, 1) == 1
        )

    @property
    def template(self) -> str | None:
        """Not all observations have templates and we want to get template strings."""
        if self.value_template is not None:
            return self.value_template.template
        return None