from . import DriverEvents as DriverEvents
from awesomeversion import AwesomeVersion
from collections.abc import Iterable
from dataclasses import dataclass, field
from enum import StrEnum
from homeassistant.config_entries import ConfigEntry as ConfigEntry
from homeassistant.const import EntityCategory as EntityCategory, Platform as Platform
from homeassistant.helpers.entity import EntityDescription as EntityDescription
from typing import Any
from zwave_js_server.client import Client as ZwaveClient
from zwave_js_server.const import LogLevel as LogLevel
from zwave_js_server.model.node import Node as ZwaveNode
from zwave_js_server.model.value import ConfigurationValue as ZwaveConfigurationValue, Value as ZwaveValue

@dataclass
class ZwaveJSData:
    client: ZwaveClient
    driver_events: DriverEvents
    old_server_log_level: LogLevel | None = ...
type ZwaveJSConfigEntry = ConfigEntry[ZwaveJSData]

@dataclass
class ZwaveValueID:
    property_: str | int
    command_class: int
    endpoint: int | None = ...
    property_key: str | int | None = ...

class ValueType(StrEnum):
    ANY = 'any'
    BOOLEAN = 'boolean'
    NUMBER = 'number'
    STRING = 'string'

class DataclassMustHaveAtLeastOne:
    def __post_init__(self) -> None: ...

@dataclass
class FirmwareVersionRange(DataclassMustHaveAtLeastOne):
    min: str | None = ...
    max: str | None = ...
    min_ver: AwesomeVersion | None = field(default=None, init=False)
    max_ver: AwesomeVersion | None = field(default=None, init=False)
    def __post_init__(self) -> None: ...

@dataclass
class PlatformZwaveDiscoveryInfo:
    node: ZwaveNode
    primary_value: ZwaveValue
    assumed_state: bool
    platform: Platform
    additional_value_ids_to_watch: set[str]

@dataclass
class ZwaveDiscoveryInfo(PlatformZwaveDiscoveryInfo):
    platform_data: Any = ...
    platform_data_template: BaseDiscoverySchemaDataTemplate | None = ...
    platform_hint: str | None = ...
    entity_registry_enabled_default: bool = ...
    entity_category: EntityCategory | None = ...

@dataclass
class ZWaveValueDiscoverySchema(DataclassMustHaveAtLeastOne):
    command_class: set[int] | None = ...
    endpoint: set[int] | None = ...
    property: set[str | int] | None = ...
    property_name: set[str] | None = ...
    property_key: set[str | int | None] | None = ...
    not_property_key: set[str | int | None] | None = ...
    type: set[str] | None = ...
    readable: bool | None = ...
    writeable: bool | None = ...
    any_available_states: set[tuple[int, str]] | None = ...
    any_available_states_keys: set[int] | None = ...
    any_available_cc_specific: set[tuple[Any, Any]] | None = ...
    value: Any | None = ...
    stateful: bool | None = ...

@dataclass
class NewZWaveDiscoverySchema:
    platform: Platform
    entity_description: EntityDescription
    entity_class: type
    primary_value: ZWaveValueDiscoverySchema
    data_template: BaseDiscoverySchemaDataTemplate | None = ...
    manufacturer_id: set[int] | None = ...
    product_id: set[int] | None = ...
    product_type: set[int] | None = ...
    firmware_version_range: FirmwareVersionRange | None = ...
    firmware_version: set[str] | None = ...
    device_class_basic: set[str | int] | None = ...
    device_class_generic: set[str | int] | None = ...
    device_class_specific: set[str | int] | None = ...
    required_values: list[ZWaveValueDiscoverySchema] | None = ...
    absent_values: list[ZWaveValueDiscoverySchema] | None = ...
    allow_multi: bool = ...
    assumed_state: bool = ...

@dataclass
class BaseDiscoverySchemaDataTemplate:
    static_data: Any | None = ...
    def resolve_data(self, value: ZwaveValue) -> Any: ...
    def values_to_watch(self, resolved_data: Any) -> Iterable[ZwaveValue | None]: ...
    def value_ids_to_watch(self, resolved_data: Any) -> set[str]: ...
    @staticmethod
    def _get_value_from_id(node: ZwaveNode, value_id_obj: ZwaveValueID) -> ZwaveValue | ZwaveConfigurationValue | None: ...
