import os.path
from typing import List

from axipy._internal._shadow_instance_factory import _shadow_manager
from axipy.da import DataManager, ProviderManager
from axipy.gui import ActiveToolPanel, Notifications
from PySide2.QtCore import QCoreApplication, QSettings
from PySide2.QtWidgets import QMainWindow

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


class AxiomaInterface:
    """
    Интерфейс для модуля.

    Вспомогательный класс для создания модулей.

    See also:
        Подробнее в главе :ref:`to_modules`.
    """

    def initialize(self, plugin_dir):
        self._plugin_dir = plugin_dir
        self._plugin_id = os.path.basename(plugin_dir)
        self._menubar_instance = None
        self._selection = None
        self._active_tool_panel = None  # type: ActiveToolPanel

    @property
    def catalog(self) -> DataManager:
        """Хранилище объектов данных."""
        return self._mainwindow().catalog()

    def window(self) -> QMainWindow:
        """
        Возвращает главное окно ГИС Аксиома. Если плагин загружается при старте аксиомы,
        то главное окно приложения будет инициализировано позже. Для решения данной
        задачи необходимо подписаться на событие
        :attr:`gui.ViewManager.mainwindow_activated`. И уже по факту инициализации
        работать главным окном. Или же, как альтернативное решение, необходимо
        переопределить :meth:`AxiomaPlugin.load_mainwindow`

        .. code-block:: python

            class Plugin(AxiomaPlugin):

                def on_activate(self):
                    print(self.window().windowTitle())

                def load(self):
                    view_manager.mainwindow_activated.connect( self.on_activate)
        """
        return self._mainwindow().widget if self._mainwindow() is not None else None

    def _mainwindow(self):
        from axipy.app import mainwindow

        return mainwindow

    @property
    def notifications(self):
        """Notifications: Отправление уведомлений в виде всплывающего окна."""
        return Notifications

    @property
    def selection(self):
        if self._selection is None:
            from axipy.gui import SelectionManager

            self._selection = SelectionManager()
        return self._selection

    @property
    def menubar(self):
        """
        Объект с функциями меню главного окна ГИС Аксиома.

        See also:
            :mod:`axipy.menubar`
        """
        if self._menubar_instance is None:
            from axipy import menubar as mb

            def apply_prefix(create_button, title_to_id, plugin_id):
                def _inner(*args, **kwargs):
                    button = create_button(*args, **kwargs)
                    button.action.setObjectName(plugin_id + "_" + title_to_id(button.action.text()))
                    return button

                return _inner

            mb.create_button = apply_prefix(mb.create_button, mb.title_to_id, self._plugin_id)
            self._menubar_instance = mb
        return self._menubar_instance

    def _make_action_id(self, title: str) -> str:
        from axipy.menubar import title_to_id

        return self._plugin_id + "_" + title_to_id(title)

    @property
    def io(self) -> ProviderManager:
        """Класс открытия/создания объектов данных."""
        from axipy import io

        return io

    def tr(self, text: str) -> str:
        """
        Ищет перевод строки.

        Производит поиск строки в загруженных файлах перевода.

        Args:
            text:
                Строка для перевода.

        Returns:
            Перевод стоки, если строка найдена. Иначе - сама переданная строка.

        Пример::

            button_name = iface.tr('My button')
        """
        return QCoreApplication.translate(self._plugin_id, text)

    @property
    def language(self) -> str:
        """Значение языка, с которым запущено приложение."""
        return _shadow_manager.core.translationLanguage()

    def active_tool_panel(self) -> ActiveToolPanel:
        """
        Возвращает экземпляр панели активного инструмента.

        Returns:
             Менеджер для управления панелью активного инструмента.
        """
        if self._active_tool_panel is None:
            self._active_tool_panel = ActiveToolPanel()
        return self._active_tool_panel

    @property
    def settings(self) -> QSettings:
        """
        Настройки модуля.

        Позволяет сохранять и загружать параметры.

        See also:
            Подробнее в документации на класс :class:`PySide2.QtCore.QSettings`.
        """
        return QSettings("axipy_plugin", self._plugin_id)

    def local_file(self, *paths) -> str:
        """
        Возвращает путь к файлу/папке относительно модуля.

        Args:
            *path: Составные относительного пути.

        Returns:
            Абсолютный путь.

        Пример::

            plugin_path = iface.local_file()
            icon_path = iface.local_file('images', '32px', 'logo.png')
        """
        return os.path.join(self._plugin_dir, *paths)
