"""Constants for sensor."""

from __future__ import annotations

from enum import StrEnum
from typing import Final

import voluptuous as vol

from homeassistant.const import (
    CONCENTRATION_GRAMS_PER_CUBIC_METER,
    CONCENTRATION_MICROGRAMS_PER_CUBIC_FOOT,
    CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
    CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
    CONCENTRATION_PARTS_PER_BILLION,
    CONCENTRATION_PARTS_PER_MILLION,
    DEGREE,
    LIGHT_LUX,
    PERCENTAGE,
    SIGNAL_STRENGTH_DECIBELS,
    SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
    UnitOfApparentPower,
    UnitOfArea,
    UnitOfBloodGlucoseConcentration,
    UnitOfConductivity,
    UnitOfDataRate,
    UnitOfElectricCurrent,
    UnitOfElectricPotential,
    UnitOfEnergy,
    UnitOfEnergyDistance,
    UnitOfFrequency,
    UnitOfInformation,
    UnitOfIrradiance,
    UnitOfLength,
    UnitOfMass,
    UnitOfPower,
    UnitOfPrecipitationDepth,
    UnitOfPressure,
    UnitOfReactiveEnergy,
    UnitOfReactivePower,
    UnitOfSoundPressure,
    UnitOfSpeed,
    UnitOfTemperature,
    UnitOfTime,
    UnitOfVolume,
    UnitOfVolumeFlowRate,
    UnitOfVolumetricFlux,
)
from homeassistant.util.unit_conversion import (
    ApparentPowerConverter,
    AreaConverter,
    BaseUnitConverter,
    BloodGlucoseConcentrationConverter,
    CarbonMonoxideConcentrationConverter,
    ConductivityConverter,
    DataRateConverter,
    DistanceConverter,
    DurationConverter,
    ElectricCurrentConverter,
    ElectricPotentialConverter,
    EnergyConverter,
    EnergyDistanceConverter,
    InformationConverter,
    MassConverter,
    MassVolumeConcentrationConverter,
    NitrogenDioxideConcentrationConverter,
    NitrogenMonoxideConcentrationConverter,
    OzoneConcentrationConverter,
    PowerConverter,
    PressureConverter,
    ReactiveEnergyConverter,
    ReactivePowerConverter,
    SpeedConverter,
    SulphurDioxideConcentrationConverter,
    TemperatureConverter,
    TemperatureDeltaConverter,
    UnitlessRatioConverter,
    VolumeConverter,
    VolumeFlowRateConverter,
)

DOMAIN: Final = "sensor"

CONF_STATE_CLASS: Final = "state_class"

ATTR_LAST_RESET: Final = "last_reset"
ATTR_STATE_CLASS: Final = "state_class"
ATTR_OPTIONS: Final = "options"


class SensorDeviceClass(StrEnum):
    """Device class for sensors."""

    # Non-numerical device classes
    DATE = "date"
    """Date.

    Unit of measurement: `None`

    ISO8601 format: https://en.wikipedia.org/wiki/ISO_8601
    """

    ENUM = "enum"
    """Enumeration.

    Provides a fixed list of options the state of the sensor can be in.

    Unit of measurement: `None`
    """

    TIMESTAMP = "timestamp"
    """Timestamp.

    Unit of measurement: `None`

    ISO8601 format: https://en.wikipedia.org/wiki/ISO_8601
    """

    # Numerical device classes, these should be aligned with NumberDeviceClass
    ABSOLUTE_HUMIDITY = "absolute_humidity"
    """Absolute humidity.

    Unit of measurement: `g/m³`, `mg/m³`
    """

    APPARENT_POWER = "apparent_power"
    """Apparent power.

    Unit of measurement: `mVA`, `VA`, `kVA`
    """

    AQI = "aqi"
    """Air Quality Index.

    Unit of measurement: `None`
    """

    AREA = "area"
    """Area

    Unit of measurement: `UnitOfArea` units
    """

    ATMOSPHERIC_PRESSURE = "atmospheric_pressure"
    """Atmospheric pressure.

    Unit of measurement: `UnitOfPressure` units
    """

    BATTERY = "battery"
    """Percentage of battery that is left.

    Unit of measurement: `%`
    """

    BLOOD_GLUCOSE_CONCENTRATION = "blood_glucose_concentration"
    """Blood glucose concentration.

    Unit of measurement: `mg/dL`, `mmol/L`
    """

    CO = "carbon_monoxide"
    """Carbon Monoxide gas concentration.

    Unit of measurement: `ppb` (parts per billion), `ppm` (parts per million), `mg/m³`, `μg/m³`
    """

    CO2 = "carbon_dioxide"
    """Carbon Dioxide gas concentration.

    Unit of measurement: `ppm` (parts per million)
    """

    CONDUCTIVITY = "conductivity"
    """Conductivity.

    Unit of measurement: `S/cm`, `mS/cm`, `μS/cm`
    """

    CURRENT = "current"
    """Current.

    Unit of measurement: `A`, `mA`
    """

    DATA_RATE = "data_rate"
    """Data rate.

    Unit of measurement: UnitOfDataRate
    """

    DATA_SIZE = "data_size"
    """Data size.

    Unit of measurement: UnitOfInformation
    """

    DISTANCE = "distance"
    """Generic distance.

    Unit of measurement: `LENGTH_*` units
    - SI /metric: `mm`, `cm`, `m`, `km`
    - USCS / imperial: `in`, `ft`, `yd`, `mi`
    """

    DURATION = "duration"
    """Fixed duration.

    Unit of measurement: `d`, `h`, `min`, `s`, `ms`, `μs`
    """

    ENERGY = "energy"
    """Energy.

    Use this device class for sensors measuring energy consumption, for example
    electric energy consumption.
    Unit of measurement: `J`, `kJ`, `MJ`, `GJ`, `mWh`, `Wh`, `kWh`, `MWh`, `GWh`, `TWh`, `cal`, `kcal`, `Mcal`, `Gcal`
    """

    ENERGY_DISTANCE = "energy_distance"
    """Energy distance.

    Use this device class for sensors measuring energy by distance, for example the amount
    of electric energy consumed by an electric car.

    Unit of measurement: `kWh/100km`, `Wh/km`, `mi/kWh`, `km/kWh`
    """

    ENERGY_STORAGE = "energy_storage"
    """Stored energy.

    Use this device class for sensors measuring stored energy, for example the amount
    of electric energy currently stored in a battery or the capacity of a battery.

    Unit of measurement: `J`, `kJ`, `MJ`, `GJ`, `mWh`, `Wh`, `kWh`, `MWh`, `GWh`, `TWh`, `cal`, `kcal`, `Mcal`, `Gcal`
    """

    FREQUENCY = "frequency"
    """Frequency.

    Unit of measurement: `Hz`, `kHz`, `MHz`, `GHz`
    """

    GAS = "gas"
    """Gas.

    Unit of measurement:
    - SI / metric: `L`, `m³`
    - USCS / imperial: `ft³`, `CCF`, `MCF`
    """

    HUMIDITY = "humidity"
    """Relative humidity.

    Unit of measurement: `%`
    """

    ILLUMINANCE = "illuminance"
    """Illuminance.

    Unit of measurement: `lx`
    """

    IRRADIANCE = "irradiance"
    """Irradiance.

    Unit of measurement:
    - SI / metric: `W/m²`
    - USCS / imperial: `BTU/(h⋅ft²)`
    """

    MOISTURE = "moisture"
    """Moisture.

    Unit of measurement: `%`
    """

    MONETARY = "monetary"
    """Amount of money.

    Unit of measurement: ISO4217 currency code

    See https://en.wikipedia.org/wiki/ISO_4217#Active_codes for active codes
    """

    NITROGEN_DIOXIDE = "nitrogen_dioxide"
    """Amount of NO2.

    Unit of measurement: `ppb` (parts per billion), `ppm` (parts per million), `μg/m³`
    """

    NITROGEN_MONOXIDE = "nitrogen_monoxide"
    """Amount of NO.

    Unit of measurement: `ppb` (parts per billion), `μg/m³`
    """

    NITROUS_OXIDE = "nitrous_oxide"
    """Amount of N2O.

    Unit of measurement: `μg/m³`
    """

    OZONE = "ozone"
    """Amount of O3.

    Unit of measurement: `ppb` (parts per billion), `ppm` (parts per million), `μg/m³`
    """

    PH = "ph"
    """Potential hydrogen (acidity/alkalinity).

    Unit of measurement: Unitless
    """

    PM1 = "pm1"
    """Particulate matter <= 1 μm.

    Unit of measurement: `μg/m³`
    """

    PM10 = "pm10"
    """Particulate matter <= 10 μm.

    Unit of measurement: `μg/m³`
    """

    PM25 = "pm25"
    """Particulate matter <= 2.5 μm.

    Unit of measurement: `μg/m³`
    """

    PM4 = "pm4"
    """Particulate matter <= 4 μm.

    Unit of measurement: `μg/m³`
    """

    POWER_FACTOR = "power_factor"
    """Power factor.

    Unit of measurement: `%`, `None`
    """

    POWER = "power"
    """Power.

    Unit of measurement: `mW`, `W`, `kW`, `MW`, `GW`, `TW`, `BTU/h`
    """

    PRECIPITATION = "precipitation"
    """Accumulated precipitation.

    Unit of measurement: UnitOfPrecipitationDepth
    - SI / metric: `cm`, `mm`
    - USCS / imperial: `in`
    """

    PRECIPITATION_INTENSITY = "precipitation_intensity"
    """Precipitation intensity.

    Unit of measurement: UnitOfVolumetricFlux
    - SI /metric: `mm/d`, `mm/h`
    - USCS / imperial: `in/d`, `in/h`
    """

    PRESSURE = "pressure"
    """Pressure.

    Unit of measurement:
    - `mbar`, `cbar`, `bar`
    - `mPa`, `Pa`, `hPa`, `kPa`
    - `inHg`
    - `psi`
    - `inH₂O`
    """

    REACTIVE_ENERGY = "reactive_energy"
    """Reactive energy.

    Unit of measurement: `varh`, `kvarh`
    """

    REACTIVE_POWER = "reactive_power"
    """Reactive power.

    Unit of measurement: `mvar`, `var`, `kvar`
    """

    SIGNAL_STRENGTH = "signal_strength"
    """Signal strength.

    Unit of measurement: `dB`, `dBm`
    """

    SOUND_PRESSURE = "sound_pressure"
    """Sound pressure.

    Unit of measurement: `dB`, `dBA`
    """

    SPEED = "speed"
    """Generic speed.

    Unit of measurement: `SPEED_*` units or `UnitOfVolumetricFlux`
    - SI /metric: `mm/d`, `mm/h`, `m/s`, `km/h`, `mm/s`
    - USCS / imperial: `in/d`, `in/h`, `in/s`, `ft/s`, `mph`
    - Nautical: `kn`
    - Beaufort: `Beaufort`
    """

    SULPHUR_DIOXIDE = "sulphur_dioxide"
    """Amount of SO2.

    Unit of measurement: `ppb` (parts per billion), `μg/m³`
    """

    TEMPERATURE = "temperature"
    """Temperature.

    Unit of measurement: `°C`, `°F`, `K`
    """

    TEMPERATURE_DELTA = "temperature_delta"
    """Difference of temperatures - Temperature range.

    Unit of measurement: `°C`, `°F`, `K`
    """

    VOLATILE_ORGANIC_COMPOUNDS = "volatile_organic_compounds"
    """Amount of VOC.

    Unit of measurement: `μg/m³`, `mg/m³`
    """

    VOLATILE_ORGANIC_COMPOUNDS_PARTS = "volatile_organic_compounds_parts"
    """Ratio of VOC.

    Unit of measurement: `ppm`, `ppb`
    """

    VOLTAGE = "voltage"
    """Voltage.

    Unit of measurement: `V`, `mV`, `μV`, `kV`, `MV`
    """

    VOLUME = "volume"
    """Generic volume.

    Unit of measurement: `VOLUME_*` units
    - SI / metric: `mL`, `L`, `m³`
    - USCS / imperial: `ft³`, `CCF`, `MCF`, `fl. oz.`, `gal` (warning: volumes expressed in
    USCS/imperial units are currently assumed to be US volumes)
    """

    VOLUME_STORAGE = "volume_storage"
    """Generic stored volume.

    Use this device class for sensors measuring stored volume, for example the amount
    of fuel in a fuel tank.

    Unit of measurement: `VOLUME_*` units
    - SI / metric: `mL`, `L`, `m³`
    - USCS / imperial: `ft³`, `CCF`, `MCF`, `fl. oz.`, `gal` (warning: volumes expressed in
    USCS/imperial units are currently assumed to be US volumes)
    """

    VOLUME_FLOW_RATE = "volume_flow_rate"
    """Generic flow rate

    Unit of measurement: UnitOfVolumeFlowRate
    - SI / metric: `m³/h`, `m³/min`, `m³/s`, `L/h`, `L/min`, `L/s`, `mL/s`
    - USCS / imperial: `ft³/min`, `gal/min`, `gal/d`
    """

    WATER = "water"
    """Water.

    Unit of measurement:
    - SI / metric: `m³`, `L`
    - USCS / imperial: `ft³`, `CCF`, `MCF`, `gal` (warning: volumes expressed in
    USCS/imperial units are currently assumed to be US volumes)
    """

    WEIGHT = "weight"
    """Generic weight, represents a measurement of an object's mass.

    Weight is used instead of mass to fit with every day language.

    Unit of measurement: `MASS_*` units
    - SI / metric: `μg`, `mg`, `g`, `kg`
    - USCS / imperial: `oz`, `lb`
    """

    WIND_DIRECTION = "wind_direction"
    """Wind direction.

    Unit of measurement: `°`
    """

    WIND_SPEED = "wind_speed"
    """Wind speed.

    Unit of measurement: `SPEED_*` units
    - SI /metric: `m/s`, `km/h`
    - USCS / imperial: `ft/s`, `mph`
    - Nautical: `kn`
    - Beaufort: `Beaufort`
    """


NON_NUMERIC_DEVICE_CLASSES = {
    SensorDeviceClass.DATE,
    SensorDeviceClass.ENUM,
    SensorDeviceClass.TIMESTAMP,
}

DEVICE_CLASSES_SCHEMA: Final = vol.All(vol.Lower, vol.Coerce(SensorDeviceClass))

# DEVICE_CLASSES is deprecated as of 2021.12
# use the SensorDeviceClass enum instead.
DEVICE_CLASSES: Final[list[str]] = [cls.value for cls in SensorDeviceClass]


class SensorStateClass(StrEnum):
    """State class for sensors."""

    MEASUREMENT = "measurement"
    """The state represents a measurement in present time."""

    MEASUREMENT_ANGLE = "measurement_angle"
    """The state represents a angle measurement in present time. Currently only degrees are supported."""

    TOTAL = "total"
    """The state represents a total amount.

    For example: net energy consumption"""

    TOTAL_INCREASING = "total_increasing"
    """The state represents a monotonically increasing total.

    For example: an amount of consumed gas"""


STATE_CLASSES_SCHEMA: Final = vol.All(vol.Lower, vol.Coerce(SensorStateClass))


STATE_CLASSES: Final[list[str]] = [cls.value for cls in SensorStateClass]

UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] = {
    SensorDeviceClass.APPARENT_POWER: ApparentPowerConverter,
    SensorDeviceClass.ABSOLUTE_HUMIDITY: MassVolumeConcentrationConverter,
    SensorDeviceClass.AREA: AreaConverter,
    SensorDeviceClass.ATMOSPHERIC_PRESSURE: PressureConverter,
    SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: BloodGlucoseConcentrationConverter,
    SensorDeviceClass.CO: CarbonMonoxideConcentrationConverter,
    SensorDeviceClass.CONDUCTIVITY: ConductivityConverter,
    SensorDeviceClass.CURRENT: ElectricCurrentConverter,
    SensorDeviceClass.DATA_RATE: DataRateConverter,
    SensorDeviceClass.DATA_SIZE: InformationConverter,
    SensorDeviceClass.DISTANCE: DistanceConverter,
    SensorDeviceClass.DURATION: DurationConverter,
    SensorDeviceClass.ENERGY: EnergyConverter,
    SensorDeviceClass.ENERGY_DISTANCE: EnergyDistanceConverter,
    SensorDeviceClass.ENERGY_STORAGE: EnergyConverter,
    SensorDeviceClass.GAS: VolumeConverter,
    SensorDeviceClass.NITROGEN_DIOXIDE: NitrogenDioxideConcentrationConverter,
    SensorDeviceClass.NITROGEN_MONOXIDE: NitrogenMonoxideConcentrationConverter,
    SensorDeviceClass.OZONE: OzoneConcentrationConverter,
    SensorDeviceClass.POWER: PowerConverter,
    SensorDeviceClass.POWER_FACTOR: UnitlessRatioConverter,
    SensorDeviceClass.PRECIPITATION: DistanceConverter,
    SensorDeviceClass.PRECIPITATION_INTENSITY: SpeedConverter,
    SensorDeviceClass.PRESSURE: PressureConverter,
    SensorDeviceClass.REACTIVE_ENERGY: ReactiveEnergyConverter,
    SensorDeviceClass.REACTIVE_POWER: ReactivePowerConverter,
    SensorDeviceClass.SULPHUR_DIOXIDE: SulphurDioxideConcentrationConverter,
    SensorDeviceClass.SPEED: SpeedConverter,
    SensorDeviceClass.TEMPERATURE: TemperatureConverter,
    SensorDeviceClass.TEMPERATURE_DELTA: TemperatureDeltaConverter,
    SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS: MassVolumeConcentrationConverter,
    SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS: UnitlessRatioConverter,
    SensorDeviceClass.VOLTAGE: ElectricPotentialConverter,
    SensorDeviceClass.VOLUME: VolumeConverter,
    SensorDeviceClass.VOLUME_STORAGE: VolumeConverter,
    SensorDeviceClass.VOLUME_FLOW_RATE: VolumeFlowRateConverter,
    SensorDeviceClass.WATER: VolumeConverter,
    SensorDeviceClass.WEIGHT: MassConverter,
    SensorDeviceClass.WIND_SPEED: SpeedConverter,
}

DEVICE_CLASS_UNITS: dict[SensorDeviceClass, set[type[StrEnum] | str | None]] = {
    SensorDeviceClass.ABSOLUTE_HUMIDITY: {
        CONCENTRATION_GRAMS_PER_CUBIC_METER,
        CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
    },
    SensorDeviceClass.APPARENT_POWER: set(UnitOfApparentPower),
    SensorDeviceClass.AQI: {None},
    SensorDeviceClass.AREA: set(UnitOfArea),
    SensorDeviceClass.ATMOSPHERIC_PRESSURE: set(UnitOfPressure),
    SensorDeviceClass.BATTERY: {PERCENTAGE},
    SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: set(UnitOfBloodGlucoseConcentration),
    SensorDeviceClass.CO: {
        CONCENTRATION_PARTS_PER_BILLION,
        CONCENTRATION_PARTS_PER_MILLION,
        CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
        CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
    },
    SensorDeviceClass.CO2: {CONCENTRATION_PARTS_PER_MILLION},
    SensorDeviceClass.CONDUCTIVITY: set(UnitOfConductivity),
    SensorDeviceClass.CURRENT: set(UnitOfElectricCurrent),
    SensorDeviceClass.DATA_RATE: set(UnitOfDataRate),
    SensorDeviceClass.DATA_SIZE: set(UnitOfInformation),
    SensorDeviceClass.DISTANCE: set(UnitOfLength),
    SensorDeviceClass.DURATION: {
        UnitOfTime.DAYS,
        UnitOfTime.HOURS,
        UnitOfTime.MINUTES,
        UnitOfTime.SECONDS,
        UnitOfTime.MILLISECONDS,
        UnitOfTime.MICROSECONDS,
    },
    SensorDeviceClass.ENERGY: set(UnitOfEnergy),
    SensorDeviceClass.ENERGY_DISTANCE: set(UnitOfEnergyDistance),
    SensorDeviceClass.ENERGY_STORAGE: set(UnitOfEnergy),
    SensorDeviceClass.FREQUENCY: set(UnitOfFrequency),
    SensorDeviceClass.GAS: {
        UnitOfVolume.CENTUM_CUBIC_FEET,
        UnitOfVolume.CUBIC_FEET,
        UnitOfVolume.CUBIC_METERS,
        UnitOfVolume.LITERS,
        UnitOfVolume.MILLE_CUBIC_FEET,
    },
    SensorDeviceClass.HUMIDITY: {PERCENTAGE},
    SensorDeviceClass.ILLUMINANCE: {LIGHT_LUX},
    SensorDeviceClass.IRRADIANCE: set(UnitOfIrradiance),
    SensorDeviceClass.MOISTURE: {PERCENTAGE},
    SensorDeviceClass.NITROGEN_DIOXIDE: {
        CONCENTRATION_PARTS_PER_BILLION,
        CONCENTRATION_PARTS_PER_MILLION,
        CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
    },
    SensorDeviceClass.NITROGEN_MONOXIDE: {
        CONCENTRATION_PARTS_PER_BILLION,
        CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
    },
    SensorDeviceClass.NITROUS_OXIDE: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
    SensorDeviceClass.OZONE: {
        CONCENTRATION_PARTS_PER_BILLION,
        CONCENTRATION_PARTS_PER_MILLION,
        CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
    },
    SensorDeviceClass.PH: {None},
    SensorDeviceClass.PM1: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
    SensorDeviceClass.PM10: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
    SensorDeviceClass.PM25: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
    SensorDeviceClass.PM4: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
    SensorDeviceClass.POWER_FACTOR: {PERCENTAGE, None},
    SensorDeviceClass.POWER: {
        UnitOfPower.MILLIWATT,
        UnitOfPower.WATT,
        UnitOfPower.KILO_WATT,
        UnitOfPower.MEGA_WATT,
        UnitOfPower.GIGA_WATT,
        UnitOfPower.TERA_WATT,
    },
    SensorDeviceClass.PRECIPITATION: set(UnitOfPrecipitationDepth),
    SensorDeviceClass.PRECIPITATION_INTENSITY: set(UnitOfVolumetricFlux),
    SensorDeviceClass.PRESSURE: set(UnitOfPressure),
    SensorDeviceClass.REACTIVE_ENERGY: set(UnitOfReactiveEnergy),
    SensorDeviceClass.REACTIVE_POWER: set(UnitOfReactivePower),
    SensorDeviceClass.SIGNAL_STRENGTH: {
        SIGNAL_STRENGTH_DECIBELS,
        SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
    },
    SensorDeviceClass.SOUND_PRESSURE: set(UnitOfSoundPressure),
    SensorDeviceClass.SPEED: {*UnitOfSpeed, *UnitOfVolumetricFlux},
    SensorDeviceClass.SULPHUR_DIOXIDE: {
        CONCENTRATION_PARTS_PER_BILLION,
        CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
    },
    SensorDeviceClass.TEMPERATURE: set(UnitOfTemperature),
    SensorDeviceClass.TEMPERATURE_DELTA: set(UnitOfTemperature),
    SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS: {
        CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
        CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
    },
    SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS: {
        CONCENTRATION_PARTS_PER_BILLION,
        CONCENTRATION_PARTS_PER_MILLION,
    },
    SensorDeviceClass.VOLTAGE: set(UnitOfElectricPotential),
    SensorDeviceClass.VOLUME: set(UnitOfVolume),
    SensorDeviceClass.VOLUME_FLOW_RATE: set(UnitOfVolumeFlowRate),
    SensorDeviceClass.VOLUME_STORAGE: set(UnitOfVolume),
    SensorDeviceClass.WATER: {
        UnitOfVolume.CENTUM_CUBIC_FEET,
        UnitOfVolume.CUBIC_FEET,
        UnitOfVolume.CUBIC_METERS,
        UnitOfVolume.GALLONS,
        UnitOfVolume.LITERS,
        UnitOfVolume.MILLE_CUBIC_FEET,
    },
    SensorDeviceClass.WEIGHT: set(UnitOfMass),
    SensorDeviceClass.WIND_DIRECTION: {DEGREE},
    SensorDeviceClass.WIND_SPEED: set(UnitOfSpeed),
}

# Maximum precision (decimals) deviation from default device class precision.
DEFAULT_PRECISION_LIMIT = 2

# Map one unit for each device class to its default precision.
# The biggest unit with the lowest precision should be used. For example, if W should
# have 0 decimals, that one should be used and not mW, even though mW also should have
# 0 decimals. Otherwise the smaller units will have more decimals than expected.
UNITS_PRECISION = {
    SensorDeviceClass.ABSOLUTE_HUMIDITY: (CONCENTRATION_GRAMS_PER_CUBIC_METER, 1),
    SensorDeviceClass.APPARENT_POWER: (UnitOfApparentPower.VOLT_AMPERE, 0),
    SensorDeviceClass.AREA: (UnitOfArea.SQUARE_CENTIMETERS, 0),
    SensorDeviceClass.ATMOSPHERIC_PRESSURE: (UnitOfPressure.PA, 0),
    SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: (
        UnitOfBloodGlucoseConcentration.MILLIGRAMS_PER_DECILITER,
        0,
    ),
    SensorDeviceClass.CONDUCTIVITY: (UnitOfConductivity.MICROSIEMENS_PER_CM, 1),
    SensorDeviceClass.CURRENT: (UnitOfElectricCurrent.MILLIAMPERE, 0),
    SensorDeviceClass.DATA_RATE: (UnitOfDataRate.KILOBITS_PER_SECOND, 0),
    SensorDeviceClass.DATA_SIZE: (UnitOfInformation.KILOBITS, 0),
    SensorDeviceClass.DISTANCE: (UnitOfLength.CENTIMETERS, 0),
    SensorDeviceClass.DURATION: (UnitOfTime.MILLISECONDS, 0),
    SensorDeviceClass.ENERGY: (UnitOfEnergy.WATT_HOUR, 0),
    SensorDeviceClass.ENERGY_DISTANCE: (UnitOfEnergyDistance.KM_PER_KILO_WATT_HOUR, 0),
    SensorDeviceClass.ENERGY_STORAGE: (UnitOfEnergy.WATT_HOUR, 0),
    SensorDeviceClass.FREQUENCY: (UnitOfFrequency.HERTZ, 0),
    SensorDeviceClass.GAS: (UnitOfVolume.MILLILITERS, 0),
    SensorDeviceClass.IRRADIANCE: (UnitOfIrradiance.WATTS_PER_SQUARE_METER, 0),
    SensorDeviceClass.POWER: (UnitOfPower.WATT, 0),
    SensorDeviceClass.PRECIPITATION: (UnitOfPrecipitationDepth.CENTIMETERS, 0),
    SensorDeviceClass.PRECIPITATION_INTENSITY: (
        UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
        0,
    ),
    SensorDeviceClass.PRESSURE: (UnitOfPressure.PA, 0),
    SensorDeviceClass.REACTIVE_POWER: (UnitOfReactivePower.VOLT_AMPERE_REACTIVE, 0),
    SensorDeviceClass.SOUND_PRESSURE: (UnitOfSoundPressure.DECIBEL, 0),
    SensorDeviceClass.SPEED: (UnitOfSpeed.MILLIMETERS_PER_SECOND, 0),
    SensorDeviceClass.TEMPERATURE: (UnitOfTemperature.KELVIN, 1),
    SensorDeviceClass.TEMPERATURE_DELTA: (UnitOfTemperature.KELVIN, 1),
    SensorDeviceClass.VOLTAGE: (UnitOfElectricPotential.VOLT, 0),
    SensorDeviceClass.VOLUME: (UnitOfVolume.MILLILITERS, 0),
    SensorDeviceClass.VOLUME_FLOW_RATE: (UnitOfVolumeFlowRate.LITERS_PER_SECOND, 0),
    SensorDeviceClass.VOLUME_STORAGE: (UnitOfVolume.MILLILITERS, 0),
    SensorDeviceClass.WATER: (UnitOfVolume.MILLILITERS, 0),
    SensorDeviceClass.WEIGHT: (UnitOfMass.GRAMS, 0),
    SensorDeviceClass.WIND_SPEED: (UnitOfSpeed.MILLIMETERS_PER_SECOND, 0),
}

DEVICE_CLASS_STATE_CLASSES: dict[SensorDeviceClass, set[SensorStateClass]] = {
    SensorDeviceClass.ABSOLUTE_HUMIDITY: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.APPARENT_POWER: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.AQI: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.AREA: set(SensorStateClass),
    SensorDeviceClass.ATMOSPHERIC_PRESSURE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.BATTERY: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.CO: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.CO2: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.CONDUCTIVITY: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.CURRENT: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.DATA_RATE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.DATA_SIZE: set(SensorStateClass),
    SensorDeviceClass.DATE: set(),
    SensorDeviceClass.DISTANCE: set(SensorStateClass),
    SensorDeviceClass.DURATION: set(SensorStateClass),
    SensorDeviceClass.ENERGY: {
        SensorStateClass.TOTAL,
        SensorStateClass.TOTAL_INCREASING,
    },
    SensorDeviceClass.ENERGY_DISTANCE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.ENERGY_STORAGE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.ENUM: set(),
    SensorDeviceClass.FREQUENCY: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.GAS: {SensorStateClass.TOTAL, SensorStateClass.TOTAL_INCREASING},
    SensorDeviceClass.HUMIDITY: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.ILLUMINANCE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.IRRADIANCE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.MOISTURE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.MONETARY: {SensorStateClass.TOTAL},
    SensorDeviceClass.NITROGEN_DIOXIDE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.NITROGEN_MONOXIDE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.NITROUS_OXIDE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.OZONE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.PH: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.PM1: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.PM10: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.PM25: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.PM4: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.POWER_FACTOR: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.POWER: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.PRECIPITATION: set(SensorStateClass),
    SensorDeviceClass.PRECIPITATION_INTENSITY: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.PRESSURE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.REACTIVE_ENERGY: {
        SensorStateClass.TOTAL,
        SensorStateClass.TOTAL_INCREASING,
    },
    SensorDeviceClass.REACTIVE_POWER: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.SIGNAL_STRENGTH: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.SOUND_PRESSURE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.SPEED: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.SULPHUR_DIOXIDE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.TEMPERATURE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.TEMPERATURE_DELTA: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.TIMESTAMP: set(),
    SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.VOLTAGE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.VOLUME: {
        SensorStateClass.TOTAL,
        SensorStateClass.TOTAL_INCREASING,
    },
    SensorDeviceClass.VOLUME_STORAGE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.VOLUME_FLOW_RATE: {SensorStateClass.MEASUREMENT},
    SensorDeviceClass.WATER: {
        SensorStateClass.TOTAL,
        SensorStateClass.TOTAL_INCREASING,
    },
    SensorDeviceClass.WEIGHT: {
        SensorStateClass.MEASUREMENT,
        SensorStateClass.TOTAL,
        SensorStateClass.TOTAL_INCREASING,
    },
    SensorDeviceClass.WIND_DIRECTION: {SensorStateClass.MEASUREMENT_ANGLE},
    SensorDeviceClass.WIND_SPEED: {SensorStateClass.MEASUREMENT},
}


STATE_CLASS_UNITS: dict[SensorStateClass, set[type[StrEnum] | str | None]] = {
    SensorStateClass.MEASUREMENT_ANGLE: {DEGREE},
}

# We translate units that were using using the legacy coding of μ \u00b5
# to units using recommended coding of μ \u03bc and
# we convert alternative accepted units to the preferred unit.
AMBIGUOUS_UNITS: dict[str | None, str] = {
    "\u00b5Sv/h": "μSv/h",  # aranet: radiation rate
    "\u00b5S/cm": UnitOfConductivity.MICROSIEMENS_PER_CM,
    "\u00b5V": UnitOfElectricPotential.MICROVOLT,
    "\u00b5g/ft³": CONCENTRATION_MICROGRAMS_PER_CUBIC_FOOT,
    "\u00b5g/m³": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
    "\u00b5mol/s⋅m²": "μmol/s⋅m²",  # fyta: light
    "\u00b5g": UnitOfMass.MICROGRAMS,
    "\u00b5s": UnitOfTime.MICROSECONDS,
    "mVAr": UnitOfReactivePower.MILLIVOLT_AMPERE_REACTIVE,
    "VAr": UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
    "kVAr": UnitOfReactivePower.KILO_VOLT_AMPERE_REACTIVE,
    "VArh": UnitOfReactiveEnergy.VOLT_AMPERE_REACTIVE_HOUR,
    "kVArh": UnitOfReactiveEnergy.KILO_VOLT_AMPERE_REACTIVE_HOUR,
}
