from typing import Any, Dict, List, NoReturn, Optional, cast

from axipy.cpp_core_dp import ShadowServiceOperation
from axipy.da.data_object import Table

from .data_provider import DataProvider
from .source import Source

__all__: List[str] = [
    "GdalSource",
    "GdalDataProvider",
]


class GdalSource(Source):
    pass


class GdalDataProvider(DataProvider):
    """
    Провайдер для растров.

    Note:
        Ссылку на провайдер можно получить через глобальную переменную :attr:`axipy.provider_manager.gdal`.
    """

    @staticmethod
    def _identifier() -> str:
        return "GdalDataProvider"

    def get_source(self, data: str, alias: Optional[str] = None, open_data: Optional[dict] = None) -> Source:
        """
        Создает источник данных.

        Args:
          data: Имя файла или описание источника данных.
          alias: Псевдоним для открываемой таблицы.
          open_data: Параметры GDAL. Передаются как пары параметр-значения, которые в конечном итоге рассматриваются как дополнительные
            параметры при открытии в функции `GDALOpenEx <https://gdal.org/en/latest/api/raster_c_api.html>`_
            Конкретные параметры необходимо смотреть в разделе "Dataset open options" для рассматриваемого источника.
        """
        pars: Dict[str, Any] = {"src": data}
        if open_data is not None:
            pars["data"] = {"openOptions": open_data}

        return GdalSource(Source._provider(self.id), Source._alias(alias), pars)

    def open(self, data: str, alias: Optional[str] = None, open_data: Optional[dict] = None) -> Table:
        """
        Открывает объект данных.

        Args:
          data: Имя файла или описание источника данных.
          alias: Псевдоним для открываемого растра.
          open_data: Параметры GDAL. Передаются как пары параметр-значения, которые в конечном итоге рассматриваются как дополнительные
            параметры при открытии в функции `GDALOpenEx <https://gdal.org/en/latest/api/raster_c_api.html>`_
            Конкретные параметры необходимо смотреть в разделе "Dataset open options" для рассматриваемого источника.

        Пример открытия растра::

            raster = axipy.provider_manager.gdal.open("PG:host=server_name dbname='db_name' user='user_name' schema='public' table='truemarble'", open_data = {'PASSWORD':'password'})
        """
        return cast(Table, self.get_source(data, alias, open_data).open())

    def get_destination(self) -> NoReturn:
        """
        Attention:
            Не поддерживается.

        Raises:
            NotImplementedError
        """
        raise NotImplementedError

    def create_open(self) -> NoReturn:
        """
        Attention:
            Не поддерживается.

        Raises:
            NotImplementedError
        """
        raise NotImplementedError

    def _register_gdal_plugin(self, path: str, name: str, suffix: str) -> None:
        """Регистрация плагина GDAL из пользовательского каталога."""
        pars = {"openWith": self.id, "path": path, "name": name, "suffix": suffix}
        return ShadowServiceOperation.registerGdalPlugin(pars)
