from typing import List

from openlog.datamodel.assay.categories import CategoriesTableDefinition


class CategoriesInterface:
    """
    Interface for categories use.

    check for interface implementation :

    - :meth:`can_import_categories`

    get available categories and table definition :

    - :meth:`get_available_categories_table`
    - :meth:`get_categories_table`
    - :meth:`get_available_categories`

    import data for category:

    - :meth:`import_categories_table`
    - :meth:`import_categories_data`

    By default, all functions are not implemented and raises :class:`InvalidInterface` exception.

    """

    class InvalidInterface(Exception):
        pass

    class UnvailableCategory(Exception):
        pass

    def can_import_categories(self) -> bool:
        """
        Return True if connection can import categories

        Returns:
            bool: False, must be implemented in interface

        """
        return False

    def get_available_categories_table(self) -> List[CategoriesTableDefinition]:
        """
        Returns available categories with table definition

        Returns:
             List[CategoriesTableDefinition]: empty list, must be implemented in interface
        """
        return []

    def get_categories_table(self, name: str) -> CategoriesTableDefinition:
        """
        Get category table definition

        Args:
            name: (str) category name

        Returns:
            CategoriesTableDefinition: if available CategoriesTableDefinition, raise :class:`UnvailableCategory` otherwise
        """
        categories = [
            c for c in self.get_available_categories_table() if c.name == name
        ]
        if len(categories):
            return categories[0]
        else:
            raise CategoriesInterface.UnvailableCategory()

    def get_available_categories(
        self, categorie: CategoriesTableDefinition
    ) -> List[str]:
        """
        Get available categories for a category table definition

        Args:
            categorie: CategoriesTableDefinition

        Returns:
            List[str]: empty list, must be implemented in interface
        """
        return []

    def import_categories_table(
        self, categories: List[CategoriesTableDefinition]
    ) -> None:
        """
        Import categories table definition

        Args:
            categories: [CategoriesTableDefinition]
        """
        raise CategoriesInterface.InvalidInterface()

    def import_categories_data(
        self, categories: CategoriesTableDefinition, data: List[str]
    ) -> None:
        """
        Import categories values into a category

        Args:
            categories: CategoriesTableDefinition
            data: List[str] categories to import
        """
        raise CategoriesInterface.InvalidInterface()
