"""Feature registry for AI MusiMuse.

This module defines :class:`FeatureRegistry`, which manages
registration and lookup of :class:`~features.definition.FeatureDefinition`
objects.  Registration rejects duplicate identifiers.
"""

from __future__ import annotations

from features.definition import FeatureCategory, FeatureDefinition


class FeatureRegistry:
    """Registry for :class:`FeatureDefinition` instances.

    Maintains definitions in registration order.  Duplicate identifiers
    are rejected.
    """

    def __init__(self) -> None:
        """Initialize an empty registry."""
        self._definitions: dict[str, FeatureDefinition] = {}

    def register(self, definition: FeatureDefinition) -> None:
        """Register a feature definition.

        Args:
            definition: The feature definition to register.

        Raises:
            ValueError: If a definition with the same identifier is
                already registered.
        """
        if definition.identifier in self._definitions:
            raise ValueError(f"Feature '{definition.identifier}' is already registered")
        self._definitions[definition.identifier] = definition

    def unregister(self, identifier: str) -> None:
        """Remove a feature definition from the registry.

        Args:
            identifier: The identifier of the definition to remove.

        Raises:
            KeyError: If no definition with the given identifier is
                registered.
        """
        if identifier not in self._definitions:
            raise KeyError(f"Feature '{identifier}' is not registered")
        del self._definitions[identifier]

    def contains(self, identifier: str) -> bool:
        """Check if a feature definition is registered.

        Args:
            identifier: The identifier to check.

        Returns:
            ``True`` if a definition with the given identifier is
            registered, ``False`` otherwise.
        """
        return identifier in self._definitions

    def get(self, identifier: str) -> FeatureDefinition:
        """Look up a feature definition by identifier.

        Args:
            identifier: The identifier to search for.

        Returns:
            The :class:`FeatureDefinition` with the given identifier.

        Raises:
            KeyError: If no definition with the given identifier is
                registered.
        """
        if identifier not in self._definitions:
            raise KeyError(f"Feature '{identifier}' is not registered")
        return self._definitions[identifier]

    def list(self) -> list[FeatureDefinition]:
        """Return all registered definitions in registration order.

        Returns:
            A list of :class:`FeatureDefinition` instances.
        """
        return list(self._definitions.values())

    def list_by_category(self, category: FeatureCategory) -> list[FeatureDefinition]:
        """Return definitions filtered by category.

        Args:
            category: The category to filter by.

        Returns:
            A list of :class:`FeatureDefinition` instances belonging
            to the given category, in registration order.
        """
        return [d for d in self._definitions.values() if d.category == category]

    def count(self) -> int:
        """Return the number of registered definitions.

        Returns:
            The total number of registered feature definitions.
        """
        return len(self._definitions)
