import abc
import logging
from . import entity_registry as entity_registry
from .entity import Entity as Entity
from .entity_component import EntityComponent as EntityComponent
from .storage import Store as Store
from .typing import ConfigType as ConfigType
from _typeshed import Incomplete
from abc import ABC, abstractmethod
from collections.abc import Awaitable, Callable, Iterable
from dataclasses import dataclass
from homeassistant.components import websocket_api as websocket_api
from homeassistant.const import CONF_ID as CONF_ID
from homeassistant.core import HomeAssistant as HomeAssistant, callback as callback
from homeassistant.exceptions import HomeAssistantError as HomeAssistantError
from homeassistant.util import slugify as slugify
from typing import Any, Generic, TypedDict
from typing_extensions import TypeVar

STORAGE_VERSION: int
SAVE_DELAY: int
CHANGE_ADDED: str
CHANGE_UPDATED: str
CHANGE_REMOVED: str
_ItemT = TypeVar('_ItemT')
_StoreT = TypeVar('_StoreT', bound='SerializedStorageCollection')
_StorageCollectionT = TypeVar('_StorageCollectionT', bound='StorageCollection')
_EntityT = TypeVar('_EntityT', bound=Entity, default=Entity)

@dataclass(slots=True)
class CollectionChangeSet:
    change_type: str
    item_id: str
    item: Any
    def __init__(self, change_type, item_id, item) -> None: ...
ChangeListener = Callable[[str, str, dict], Awaitable[None]]
ChangeSetListener = Callable[[Iterable[CollectionChangeSet]], Awaitable[None]]

class CollectionError(HomeAssistantError): ...

class ItemNotFound(CollectionError):
    item_id: Incomplete
    def __init__(self, item_id: str) -> None: ...

class IDManager:
    collections: Incomplete
    def __init__(self) -> None: ...
    def add_collection(self, collection: dict[str, Any]) -> None: ...
    def has_id(self, item_id: str) -> bool: ...
    def generate_id(self, suggestion: str) -> str: ...

class CollectionEntity(Entity, metaclass=abc.ABCMeta):
    @classmethod
    @abstractmethod
    def from_storage(cls, config: ConfigType) -> CollectionEntity: ...
    @classmethod
    @abstractmethod
    def from_yaml(cls, config: ConfigType) -> CollectionEntity: ...
    @abstractmethod
    async def async_update_config(self, config: ConfigType) -> None: ...

class ObservableCollection(ABC, Generic[_ItemT]):
    id_manager: Incomplete
    data: Incomplete
    listeners: Incomplete
    change_set_listeners: Incomplete
    def __init__(self, id_manager: IDManager | None) -> None: ...
    def async_items(self) -> list[_ItemT]: ...
    def async_add_listener(self, listener: ChangeListener) -> Callable[[], None]: ...
    def async_add_change_set_listener(self, listener: ChangeSetListener) -> Callable[[], None]: ...
    async def notify_changes(self, change_sets: Iterable[CollectionChangeSet]) -> None: ...

class YamlCollection(ObservableCollection[dict]):
    logger: Incomplete
    def __init__(self, logger: logging.Logger, id_manager: IDManager | None = None) -> None: ...
    @staticmethod
    def create_entity(entity_class: type[CollectionEntity], config: ConfigType) -> CollectionEntity: ...
    async def async_load(self, data: list[dict]) -> None: ...

class SerializedStorageCollection(TypedDict):
    items: list[dict[str, Any]]

class StorageCollection(ObservableCollection[_ItemT], Generic[_ItemT, _StoreT], metaclass=abc.ABCMeta):
    store: Incomplete
    def __init__(self, store: Store[_StoreT], id_manager: IDManager | None = None) -> None: ...
    @staticmethod
    def create_entity(entity_class: type[CollectionEntity], config: ConfigType) -> CollectionEntity: ...
    @property
    def hass(self) -> HomeAssistant: ...
    async def _async_load_data(self) -> _StoreT | None: ...
    async def async_load(self) -> None: ...
    @abstractmethod
    async def _process_create_data(self, data: dict) -> dict: ...
    @abstractmethod
    def _get_suggested_id(self, info: dict) -> str: ...
    @abstractmethod
    async def _update_data(self, item: _ItemT, update_data: dict) -> _ItemT: ...
    @abstractmethod
    def _create_item(self, item_id: str, data: dict) -> _ItemT: ...
    @abstractmethod
    def _deserialize_item(self, data: dict) -> _ItemT: ...
    @abstractmethod
    def _serialize_item(self, item_id: str, item: _ItemT) -> dict: ...
    async def async_create_item(self, data: dict) -> _ItemT: ...
    async def async_update_item(self, item_id: str, updates: dict) -> _ItemT: ...
    async def async_delete_item(self, item_id: str) -> None: ...
    def _async_schedule_save(self) -> None: ...
    def _base_data_to_save(self) -> SerializedStorageCollection: ...
    @abstractmethod
    def _data_to_save(self) -> _StoreT: ...

class DictStorageCollection(StorageCollection[dict, SerializedStorageCollection], metaclass=abc.ABCMeta):
    def _create_item(self, item_id: str, data: dict) -> dict: ...
    def _deserialize_item(self, data: dict) -> dict: ...
    def _serialize_item(self, item_id: str, item: dict) -> dict: ...
    def _data_to_save(self) -> SerializedStorageCollection: ...

class IDLessCollection(YamlCollection):
    counter: int
    async def async_load(self, data: list[dict]) -> None: ...

def sync_entity_lifecycle(hass: HomeAssistant, domain: str, platform: str, entity_component: EntityComponent[_EntityT], collection: StorageCollection | YamlCollection, entity_class: type[CollectionEntity]) -> None: ...

class StorageCollectionWebsocket(Generic[_StorageCollectionT]):
    storage_collection: Incomplete
    api_prefix: Incomplete
    model_name: Incomplete
    create_schema: Incomplete
    update_schema: Incomplete
    def __init__(self, storage_collection: _StorageCollectionT, api_prefix: str, model_name: str, create_schema: dict, update_schema: dict) -> None: ...
    @property
    def item_id_key(self) -> str: ...
    def async_setup(self, hass: HomeAssistant, *, create_list: bool = True, create_create: bool = True) -> None: ...
    def ws_list_item(self, hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict) -> None: ...
    async def ws_create_item(self, hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict) -> None: ...
    async def ws_update_item(self, hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict) -> None: ...
    async def ws_delete_item(self, hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict) -> None: ...

class DictStorageCollectionWebsocket(StorageCollectionWebsocket[DictStorageCollection]): ...
