from collections.abc import Iterator
from typing import TYPE_CHECKING, Optional

from snowflake.core import PollingOperation
from snowflake.core._common import CreateMode
from snowflake.core._internal.telemetry import api_telemetry
from snowflake.core._internal.utils import deprecated
from snowflake.core.image_repository._generated.api.image_repository_api_base import (
    ImageRepositoryCollectionBase,
    ImageRepositoryResourceBase,
)


if TYPE_CHECKING:
    from snowflake.core.schema import SchemaResource


from snowflake.core.image_repository._generated.models.image_repository import ImageRepositoryModel as ImageRepository


class ImageRepositoryCollection(ImageRepositoryCollectionBase):
    """Represents the collection operations on the Snowflake Image Repository resource.

    With this collection, you can create, iterate through, and search for image repositories that you have access to
    in the current context.

    Examples
    ________
    Creating an image repository instance:

    >>> image_repository = ImageRepository(name="my_image_repository")
    >>> image_repositories = root.databases["my_db"].schemas["my_schema"].image_repositories
    >>> image_repositories.create(image_repository)
    """

    def __init__(self, schema: "SchemaResource") -> None:
        super().__init__(schema, ImageRepositoryResource)

    @api_telemetry
    def create(  # type: ignore[override]
        self,
        image_repository: ImageRepository,
        mode: CreateMode = CreateMode.error_if_exists,
    ) -> "ImageRepositoryResource":
        """Create an image repository in Snowflake.

        Parameters
        __________
        image_repository: ImageRepository
            The ``ImageRepository`` object, together with the ``ImageRepository``'s properties:
            name;
        mode: CreateMode, optional
            One of the following enum values.

            ``CreateMode.error_if_exists``: Throw an :class:`snowflake.core.exceptions.ConflictError` if the image
            repository already exists in Snowflake. Equivalent to SQL ``create image repository <name> ...``.

            ``CreateMode.or_replace``: Replace if the image repository already exists in Snowflake. Equivalent to SQL
            ``create or replace image repository <name> ...``.

            ``CreateMode.if_not_exists``: Do nothing if the image repository already exists in Snowflake.
            Equivalent to SQL ``create image repository <name> if not exists...``

            Default value is ``CreateMode.error_if_exists``.

        Examples
        ________
        Creating an image repository, replacing an existing image repository with the same name:

        >>> image_repository = ImageRepository(name="my_image_repository")
        >>> image_repositories = root.databases["my_db"].schemas["my_schema"].image_repositories
        >>> image_repositories.create(image_repository, mode=CreateMode.or_replace)
        """
        return super().create(image_repository=image_repository._to_model(), mode=mode)

    @api_telemetry
    def create_async(  # type: ignore[override]
        self,
        image_repository: ImageRepository,
        mode: CreateMode = CreateMode.error_if_exists,
    ) -> PollingOperation["ImageRepositoryResource"]:
        """An asynchronous version of :func:`create`.

        Refer to :class:`~snowflake.core.PollingOperation` for more information on asynchronous execution and
        the return type.
        """  # noqa: D401
        return super().create_async(image_repository=image_repository._to_model(), mode=mode)

    @api_telemetry
    def iter(self, *, like: Optional[str] = None) -> Iterator[ImageRepository]:  # type: ignore[override]
        """Iterate through ``ImageRepository`` objects from Snowflake, filtering on any optional 'like' pattern.

        Parameters
        __________
        like: str, optional
            A case-insensitive string functioning as a filter, with support for SQL
            wildcard characters (% and _).

        Examples
        ________
        Showing all image repositories that you have access to see:

        >>> image_repositories = image_repository_collection.iter()

        Showing information of the exact image repository you want to see:

        >>> image_repositories = image_repository_collection.iter(like="your-image-repository-name")

        Showing image repositories starting with 'your-image-repository-name-':

        >>> image_repositories = image_repository_collection.iter(like="your-image-repository-name-%")

        Using a for loop to retrieve information from iterator:

        >>> for image_repository in image_repositories:
        >>>     print(image_repository.name)
        """
        image_repositories = super().iter(like=like)
        return map(ImageRepository._from_model, iter(image_repositories))

    @api_telemetry
    def iter_async(self, *, like: Optional[str] = None) -> PollingOperation[Iterator[ImageRepository]]:  # type: ignore[override]
        """An asynchronous version of :func:`iter`.

        Refer to :class:`~snowflake.core.PollingOperation` for more information on asynchronous execution and
        the return type.
        """  # noqa: D401
        future = super().iter_async(like=like)
        return PollingOperation(future, lambda rest_models: map(ImageRepository._from_model, iter(rest_models)))


class ImageRepositoryResource(ImageRepositoryResourceBase):
    """Represents a reference to a Snowflake image repository.

    With this image repository reference, you can fetch information about an image repository,
    as well as perform certain actions on it.
    """

    _plural_name = "image_repositories"

    @api_telemetry
    def fetch(self) -> ImageRepository:  # type: ignore[override]
        """Fetch the details of an image repository.

        Examples
        ________
        Fetching a reference to an image repository to print its name and properties:

        >>> my_image_repository = image_repository_reference.fetch()
        >>> print(my_image_repository.name)
        """
        return ImageRepository._from_model(super().fetch())

    @api_telemetry
    def fetch_async(self) -> PollingOperation[ImageRepository]:  # type: ignore[override]
        """An asynchronous version of :func:`fetch`.

        Refer to :class:`~snowflake.core.PollingOperation` for more information on asynchronous execution and
        the return type.
        """  # noqa: D401
        future = super().fetch_async()
        return PollingOperation(future, lambda rest_model: ImageRepository._from_model(rest_model))

    @api_telemetry
    @deprecated("drop")
    def delete(self) -> None:
        """Delete this image repository.

        Examples
        ________
        Deleting an image repository using its reference:

        >>> image_repository_reference.delete()
        """
        self.drop()
