# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

"""Data catalog providers."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Protocol

import datafusion._internal as df_internal

if TYPE_CHECKING:
    import pyarrow as pa

    from datafusion import DataFrame, SessionContext
    from datafusion.context import TableProviderExportable
    from datafusion.expr import CreateExternalTable

try:
    from warnings import deprecated  # Python 3.13+
except ImportError:
    from typing_extensions import deprecated  # Python 3.12


__all__ = [
    "Catalog",
    "CatalogList",
    "CatalogProvider",
    "CatalogProviderList",
    "Schema",
    "SchemaProvider",
    "Table",
    "TableProviderFactory",
]


class CatalogList:
    """DataFusion data catalog list."""

    def __init__(self, catalog_list: df_internal.catalog.RawCatalogList) -> None:
        """This constructor is not typically called by the end user."""
        self.catalog_list = catalog_list

    def __repr__(self) -> str:
        """Print a string representation of the catalog list."""
        return self.catalog_list.__repr__()

    def names(self) -> set[str]:
        """This is an alias for `catalog_names`."""
        return self.catalog_names()

    def catalog_names(self) -> set[str]:
        """Returns the list of schemas in this catalog."""
        return self.catalog_list.catalog_names()

    @staticmethod
    def memory_catalog(ctx: SessionContext | None = None) -> CatalogList:
        """Create an in-memory catalog provider list."""
        catalog_list = df_internal.catalog.RawCatalogList.memory_catalog(ctx)
        return CatalogList(catalog_list)

    def catalog(self, name: str = "datafusion") -> Catalog:
        """Returns the catalog with the given ``name`` from this catalog."""
        catalog = self.catalog_list.catalog(name)

        return (
            Catalog(catalog)
            if isinstance(catalog, df_internal.catalog.RawCatalog)
            else catalog
        )

    def register_catalog(
        self,
        name: str,
        catalog: Catalog | CatalogProvider | CatalogProviderExportable,
    ) -> Catalog | None:
        """Register a catalog with this catalog list."""
        if isinstance(catalog, Catalog):
            return self.catalog_list.register_catalog(name, catalog.catalog)
        return self.catalog_list.register_catalog(name, catalog)


class Catalog:
    """DataFusion data catalog."""

    def __init__(self, catalog: df_internal.catalog.RawCatalog) -> None:
        """This constructor is not typically called by the end user."""
        self.catalog = catalog

    def __repr__(self) -> str:
        """Print a string representation of the catalog."""
        return self.catalog.__repr__()

    def names(self) -> set[str]:
        """This is an alias for `schema_names`."""
        return self.schema_names()

    def schema_names(self) -> set[str]:
        """Returns the list of schemas in this catalog."""
        return self.catalog.schema_names()

    @staticmethod
    def memory_catalog(ctx: SessionContext | None = None) -> Catalog:
        """Create an in-memory catalog provider."""
        catalog = df_internal.catalog.RawCatalog.memory_catalog(ctx)
        return Catalog(catalog)

    def schema(self, name: str = "public") -> Schema:
        """Returns the database with the given ``name`` from this catalog."""
        schema = self.catalog.schema(name)

        return (
            Schema(schema)
            if isinstance(schema, df_internal.catalog.RawSchema)
            else schema
        )

    def register_schema(
        self,
        name: str,
        schema: Schema | SchemaProvider | SchemaProviderExportable,
    ) -> Schema | None:
        """Register a schema with this catalog."""
        if isinstance(schema, Schema):
            return self.catalog.register_schema(name, schema._raw_schema)
        return self.catalog.register_schema(name, schema)

    def deregister_schema(self, name: str, cascade: bool = True) -> Schema | None:
        """Deregister a schema from this catalog."""
        return self.catalog.deregister_schema(name, cascade)


class Schema:
    """DataFusion Schema."""

    def __init__(self, schema: df_internal.catalog.RawSchema) -> None:
        """This constructor is not typically called by the end user."""
        self._raw_schema = schema

    def __repr__(self) -> str:
        """Print a string representation of the schema."""
        return self._raw_schema.__repr__()

    @staticmethod
    def memory_schema(ctx: SessionContext | None = None) -> Schema:
        """Create an in-memory schema provider."""
        schema = df_internal.catalog.RawSchema.memory_schema(ctx)
        return Schema(schema)

    def names(self) -> set[str]:
        """This is an alias for `table_names`."""
        return self.table_names()

    def table_names(self) -> set[str]:
        """Returns the list of all tables in this schema."""
        return self._raw_schema.table_names

    def table(self, name: str) -> Table:
        """Return the table with the given ``name`` from this schema."""
        return Table(self._raw_schema.table(name))

    def register_table(
        self,
        name: str,
        table: Table | TableProviderExportable | DataFrame | pa.dataset.Dataset,
    ) -> None:
        """Register a table in this schema."""
        return self._raw_schema.register_table(name, table)

    def deregister_table(self, name: str) -> None:
        """Deregister a table provider from this schema."""
        return self._raw_schema.deregister_table(name)

    def table_exist(self, name: str) -> bool:
        """Determines if a table exists in this schema."""
        return self._raw_schema.table_exist(name)


class Table:
    """A DataFusion table.

    Internally we currently support the following types of tables:

    - Tables created using built-in DataFusion methods, such as
      reading from CSV or Parquet
    - pyarrow datasets
    - DataFusion DataFrames, which will be converted into a view
    - Externally provided tables implemented with the FFI PyCapsule
      interface (advanced)
    """

    __slots__ = ("_inner",)

    def __init__(
        self,
        table: Table | TableProviderExportable | DataFrame | pa.dataset.Dataset,
        ctx: SessionContext | None = None,
    ) -> None:
        """Constructor."""
        self._inner = df_internal.catalog.RawTable(table, ctx)

    def __repr__(self) -> str:
        """Print a string representation of the table."""
        return repr(self._inner)

    @staticmethod
    @deprecated("Use Table() constructor instead.")
    def from_dataset(dataset: pa.dataset.Dataset) -> Table:
        """Turn a :mod:`pyarrow.dataset` ``Dataset`` into a :class:`Table`."""
        return Table(dataset)

    @property
    def schema(self) -> pa.Schema:
        """Returns the schema associated with this table."""
        return self._inner.schema

    @property
    def kind(self) -> str:
        """Returns the kind of table."""
        return self._inner.kind


class TableProviderFactory(ABC):
    """Abstract class for defining a Python based Table Provider Factory."""

    @abstractmethod
    def create(self, cmd: CreateExternalTable) -> Table:
        """Create a table using the :class:`CreateExternalTable`."""
        ...


class TableProviderFactoryExportable(Protocol):
    """Type hint for object that has __datafusion_table_provider_factory__ PyCapsule.

    https://docs.rs/datafusion/latest/datafusion/catalog/trait.TableProviderFactory.html
    """

    def __datafusion_table_provider_factory__(self, session: Any) -> object: ...


class CatalogProviderList(ABC):
    """Abstract class for defining a Python based Catalog Provider List."""

    @abstractmethod
    def catalog_names(self) -> set[str]:
        """Set of the names of all catalogs in this catalog list."""
        ...

    @abstractmethod
    def catalog(
        self, name: str
    ) -> CatalogProviderExportable | CatalogProvider | Catalog | None:
        """Retrieve a specific catalog from this catalog list."""
        ...

    def register_catalog(  # noqa: B027
        self, name: str, catalog: CatalogProviderExportable | CatalogProvider | Catalog
    ) -> None:
        """Add a catalog to this catalog list.

        This method is optional. If your catalog provides a fixed list of catalogs, you
        do not need to implement this method.
        """


class CatalogProviderListExportable(Protocol):
    """Type hint for object that has __datafusion_catalog_provider_list__ PyCapsule.

    https://docs.rs/datafusion/latest/datafusion/catalog/trait.CatalogProviderList.html
    """

    def __datafusion_catalog_provider_list__(self, session: Any) -> object: ...


class CatalogProvider(ABC):
    """Abstract class for defining a Python based Catalog Provider."""

    @abstractmethod
    def schema_names(self) -> set[str]:
        """Set of the names of all schemas in this catalog."""
        ...

    @abstractmethod
    def schema(self, name: str) -> Schema | None:
        """Retrieve a specific schema from this catalog."""
        ...

    def register_schema(  # noqa: B027
        self, name: str, schema: SchemaProviderExportable | SchemaProvider | Schema
    ) -> None:
        """Add a schema to this catalog.

        This method is optional. If your catalog provides a fixed list of schemas, you
        do not need to implement this method.
        """

    def deregister_schema(self, name: str, cascade: bool) -> None:  # noqa: B027
        """Remove a schema from this catalog.

        This method is optional. If your catalog provides a fixed list of schemas, you
        do not need to implement this method.

        Args:
            name: The name of the schema to remove.
            cascade: If true, deregister the tables within the schema.
        """


class CatalogProviderExportable(Protocol):
    """Type hint for object that has __datafusion_catalog_provider__ PyCapsule.

    https://docs.rs/datafusion/latest/datafusion/catalog/trait.CatalogProvider.html
    """

    def __datafusion_catalog_provider__(self, session: Any) -> object: ...


class SchemaProvider(ABC):
    """Abstract class for defining a Python based Schema Provider."""

    def owner_name(self) -> str | None:
        """Returns the owner of the schema.

        This is an optional method. The default return is None.
        """
        return None

    @abstractmethod
    def table_names(self) -> set[str]:
        """Set of the names of all tables in this schema."""
        ...

    @abstractmethod
    def table(self, name: str) -> Table | None:
        """Retrieve a specific table from this schema."""
        ...

    def register_table(  # noqa: B027
        self, name: str, table: Table | TableProviderExportable | Any
    ) -> None:
        """Add a table to this schema.

        This method is optional. If your schema provides a fixed list of tables, you do
        not need to implement this method.
        """

    def deregister_table(self, name: str, cascade: bool) -> None:  # noqa: B027
        """Remove a table from this schema.

        This method is optional. If your schema provides a fixed list of tables, you do
        not need to implement this method.
        """

    @abstractmethod
    def table_exist(self, name: str) -> bool:
        """Returns true if the table exists in this schema."""
        ...


class SchemaProviderExportable(Protocol):
    """Type hint for object that has __datafusion_schema_provider__ PyCapsule.

    https://docs.rs/datafusion/latest/datafusion/catalog/trait.SchemaProvider.html
    """

    def __datafusion_schema_provider__(self, session: Any) -> object: ...
