from typing import List, NoReturn, Optional

from ..data_object import DataObject
from .data_provider import DataProvider
from .source import Source
from .web_utils import WebOpenData

__all__: List[str] = [
    "TmsSource",
    "TmsDataProvider",
]


class TmsSource(Source):
    pass


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

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

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

    # noinspection PyPep8Naming
    def get_source(
        self,
        templateUrl: str,
        minLevel: int = 0,
        maxLevel: int = 19,
        size: tuple = (256, 256),
        type_address: str = "xyz",
        watermark: str = "",
        watermark_style: str = "",
        prj: Optional[str] = None,
        live_time: int = 0,
        alias: Optional[str] = None,
        maxAttempts: int = 0,
        noLocalCache: bool = False,
        extra_data: Optional[WebOpenData] = None,
    ) -> Source:
        """
        Создает источник данных.

        Args:
            templateUrl: Шаблон для запроса данных. Например, `https://maps.axioma-gis.ru/osm/{LEVEL}/{ROW}/{COL}.png`
            minLevel: Минимальный уровень показа
            maxLevel: Максимальный уровень показа
            size: Размер тайлов
            type_address: Тип адресации к тайлам. Поддерживается два значения: `xyz` и `quadkey`
            watermark: Ссылка на правообладателя
            watermark_style: Стиль оформления текста, с которым на карте будут отображаться данные о правообладателе.
            prj: Строка с Системой Координат. Если None, то используется значение по умолчанию (`CoordSys Earth Projection 10, 157, 'm'`)
            live_time: время жизни тайла в секундах. Если равно 0, то значение не учитывается.
            alias: Псевдоним для открываемой таблицы.
            maxAttempts: Максимальное количество попыток запроса. Значение 0 соответствует значению по умолчанию.
            noLocalCache: Не использовать локальный кэш
            extra_data: Дополнительные параметры подключения
        """
        pars = {
            "src": templateUrl,
            "minLevel": minLevel,
            "maxLevel": maxLevel,
            "tileSize": "{}x{}".format(size[0], size[1]),
            "typeAddress": type_address,
            "watermarkText": watermark,
            "watermarkStyle": watermark_style,
            "liveTime": live_time,
            "maxRequests": maxAttempts,
            "noCache": noLocalCache,
        }
        if extra_data:
            if "header" in extra_data:
                pars["header"] = extra_data.header
            if "authenticator" in extra_data:
                pars["authenticator"] = extra_data.authenticator
        return TmsSource(Source._provider(self.id), Source._prj(prj), Source._alias(alias), pars)

    # noinspection PyPep8Naming
    def open(
        self,
        templateUrl: str,
        minLevel: int = 0,
        maxLevel: int = 19,
        size: tuple = (256, 256),
        type_address: str = "xyz",
        watermark: str = "",
        watermark_style: str = "",
        prj: Optional[str] = None,
        live_time: int = 0,
        alias: Optional[str] = None,
        maxAttempts: int = 0,
        noLocalCache: bool = False,
        extra_data: Optional[WebOpenData] = None,
    ) -> DataObject:
        """
        Открывает объект данных.

        Args:
            templateUrl: Шаблон для запроса данных. Например, `https://maps.axioma-gis.ru/osm/{LEVEL}/{ROW}/{COL}.png`
            minLevel: Минимальный уровень показа
            maxLevel: Максимальный уровень показа
            size: Размер тайлов
            type_address: Тип адресации к тайлам. Поддерживается два значения: `xyz` и `quadkey`
            watermark: Ссылка на правообладателя
            watermark_style: Стиль оформления текста, с которым на карте будут отображаться данные о правообладателе.
            prj: Строка с Системой Координат. Если None, то используется значение по умолчанию (`CoordSys Earth Projection 10, 157, 'm'`)
            live_time: время жизни тайла в секундах. Если равно 0, то значение не учитывается.
            alias: Псевдоним для открываемого источника данных.
            maxAttempts: Максимальное количество попыток запроса. Значение 0 соответствует значению по умолчанию.
            noLocalCache: Не использовать локальный кэш
            extra_data: Дополнительные параметры подключения


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

            prj_mercator = 'CoordSys Earth Projection 10, 104, "m", 0 Bounds (-20037508.34, -20037508.34) (20037508.34, 20037508.34)'
            osm_raster = provider_manager.tms.open('http://maps.axioma-gis.ru/osm/{LEVEL}/{ROW}/{COL}.png', prj=prj_mercator)
            osm_layer = Layer.create(osm_raster)
            map = Map([ osm_layer ])
            view_manager.create_mapview(map)
        """
        return self.get_source(
            templateUrl,
            minLevel,
            maxLevel,
            size,
            type_address,
            watermark,
            watermark_style,
            prj,
            live_time,
            alias,
            maxAttempts,
            noLocalCache,
            extra_data,
        ).open()

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

        Raises:
            NotImplementedError
        """
        raise NotImplementedError

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

        Raises:
            NotImplementedError
        """
        raise NotImplementedError
