from functools import cached_property
from typing import Iterable, Iterator, List

from axipy._internal._decorator import _experimental_class
from axipy._internal._shadow_instance_factory import _shadow_manager
from axipy._internal._utils import _AxiRepr, _AxiReprMeta, _Singleton
from axipy.cpp_gui import ShadowClipboardManager
from axipy.da import Feature
from axipy.da.feature import _FeatureIterator
from PySide2.QtCore import Signal
from PySide2.QtGui import QClipboard
from PySide2.QtWidgets import QApplication

__all__: List[str] = [
    "_ClipboardManager",
]


@_experimental_class()
class _ClipboardManager(_Singleton, _AxiRepr, metaclass=_AxiReprMeta):
    """
    Менеджер работы с буфером обмена.

    Note:
        Создание :class:`axipy._ClipboardManager` не требуется,
        используйте объект :attr:`axipy._clipboard_manager`.
    """

    @cached_property
    def _shadow(self) -> "ShadowClipboardManager":
        return ShadowClipboardManager(_shadow_manager.gui)

    @property
    def _clipboard(self) -> QClipboard:
        return QApplication.clipboard()

    @property
    def changed(self) -> Signal:
        """
        Содержимое буфера обмена было изменено.

        Пример::

            _clipboard_manager.changed.connect(lambda: print("Clipboard data has been changed"))

        :rtype: Signal[]
        """
        return self._clipboard.dataChanged

    @property
    def mime_data(self) -> List[str]:
        """
        Тип содержимого на данный момент контента.
        Одновременно может содержаться данные в разных форматах.
        """
        return self._clipboard.mimeData().formats()

    def feature_to_clipboard(self, feature: Feature) -> None:
        """
        Копирование записи в буфер обмена.
        Копирование производится во внутреннем формате, а так же атрибутика копируется в формате `HTML` и `TEXT`.

        Args:
            feature: Запись

        Пример::

            feature = Feature(
                    {'Country': 'Страна'},
                    geometry=Polygon((0,0), (10,10), (10,0), (0,0))
            )

            axipy._clipboard_manager.feature_to_clipboard(feature)
        """
        self._shadow.feature_to_clipboard(feature._shadow)

    def __features_to_clipboard(self, features: Iterable[Feature], params: dict) -> None:
        self._shadow.features_to_clipboard((f._shadow for f in features), params)

    def features_to_clipboard(self, features: Iterable[Feature]) -> None:
        """
        Копирование в буфер курсора.

        Args:
            features: Записи для копирования.

        Пример сохранения в буфер результата запроса::

            qry = data_manager.query('select * from world where Country like "A%"')
            axipy._clipboard_manager.features_to_clipboard(qry.items())
        """
        self.__features_to_clipboard(features, {"format": "native"})

    def features_to_clipboard_as_html(self, features: Iterable[Feature]) -> None:
        """
        Копирование в буфер обмена семантики из курсора в виде HTML.
        Это может потребоваться при вставке данных в пакеты Office.

        Args:
            features: Записи для копирования.

        Пример::

            qry = data_manager.query('select * from world where Country like "A%"')
            axipy._clipboard_manager.features_to_clipboard_as_html(qry.items())
        """
        self.__features_to_clipboard(features, {"format": "html"})

    def features_to_clipboard_as_text(self, features: Iterable[Feature], separator: str = "\t") -> None:
        """
        Копирование в буфер обмена семантики из курсора в виде CSV.

        Args:
            features: Записи для копирования.

        Пример::

            qry = data_manager.query('select * from world where Country like "A%"')
            axipy._clipboard_manager.features_to_clipboard_as_csv(qry.items())
        """
        params = {"format": "text", "separator": separator}
        self.__features_to_clipboard(features, params)

    def features_from_clipboard(self) -> Iterator[Feature]:
        """
        Получение данных в виде итератора данных из буфера обмена.

        Пример::

            items = axipy._clipboard_manager.features_from_clipboard()
            for f in items:
                print('Feature:', f['Country'])
        """
        return _FeatureIterator(self._shadow.cursor_from_clipboard())
