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

from axipy.da.data_object import DataObject

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

from PySide2.QtGui import QColor

__all__: List[str] = [
    "WmsSource",
    "WmsDataProvider",
]


class WmsSource(Source):
    pass


class WmsDataProvider(DataProvider):
    """
    Провайдер для Web Map Service.

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

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

    def get_source(
        self,
        url_capabilities: str,
        layers: List[str],
        image_format: str = "image/png",
        prj: Optional[str] = None,
        style: Optional[str] = None,
        alias: Optional[str] = None,
        extra_data: Optional[WebOpenData] = None,
        color: Optional[QColor] = None,
        size: Optional[Union[str, tuple]] = None,
    ) -> Source:
        """
        Создает источник данных.

        Args:
            url_capabilities: URL с метаданными capabilities.
            layers: Перечень слоев в виде списка.
            prj: Строка Системы Координат
            image_format: Формат выходного растра.
            style: Наименование стиля оформления.
            alias: Псевдоним для открываемого источника данных.
            extra_data: Дополнительные параметры подключения
            color: Цвет подложки растра. Если None, устанавливается прозрачной
            size: Максимальный размер выходного растра.
        """
        pars: Dict[str, Any] = {
            "src": url_capabilities,
            "layers": layers,
            "imageFormat": image_format,
            "style": style,
        }
        if color is None:
            pars["transparent"] = "true"
        else:
            pars["bgColor"] = color.name()
        if size is not None:
            pars["size"] = size if isinstance(size, str) else f'{size[0]}*{size[1]}'
        if extra_data:
            if "header" in extra_data:
                pars["header"] = extra_data.header
            if "authenticator" in extra_data:
                pars["authenticator"] = extra_data.authenticator
        return WmsSource(Source._provider(self.id), Source._alias(alias), Source._prj(prj), pars)

    def open(
        self,
        url_capabilities: str,
        layers: List[str],
        image_format: str = "image/png",
        prj: Optional[str] = None,
        style: Optional[str] = None,
        alias: Optional[str] = None,
        extra_data: Optional[WebOpenData] = None,
        color: Optional[QColor] = None,
        size: Optional[Union[str, tuple]] = None,
    ) -> DataObject:
        """
        Открывает объект данных.

        Args:
            url_capabilities: URL с метаданными capabilities.
            layers: Перечень слоев в виде списка.
            prj: Строка Системы Координат
            image_format: Формат выходного растра.
            style: Наименование стиля оформления.
            alias: Псевдоним для открываемого источника данных.
            extra_data: Дополнительные параметры подключения
            color: Цвет подложки растра. Если None, устанавливается прозрачной
            size: Максимальный размер выходного растра.

        Пример::

            wms_raster = provider_manager.wms.open('http://www.mapinfo.com/miwms', ['World'], prj='EPSG:4326', style='AreaStyleGreen')
        """
        return self.get_source(url_capabilities, layers, image_format, prj, style, alias, extra_data, color, size).open()

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

        Raises:
            NotImplementedError
        """
        raise NotImplementedError

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

        Raises:
            NotImplementedError
        """
        raise NotImplementedError
