# 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",
]


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: ...
