from typing import List

from axipy._internal._shadow_instance_factory import _shadow_manager
from axipy.cpp_core_core import ShadowTabFile
from PySide2.QtCore import QFileInfo

from .data_object import DataObject

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


class TabFile:
    """Класс поддержки файла TAB формата MapInfo."""

    def __init__(self) -> None:
        self._shadow = ShadowTabFile(_shadow_manager.core)

    def generate_tab(
        self,
        data_object: DataObject,
        out_file: str,
        override: bool = True,
        linked_file: bool = True,
    ) -> bool:
        """
        Генерирует файл TAB для переданного открытого объекта, если такую возможность
        поддерживает провайдер данных.

        Args:
            data_object: открытый объект данных, для которого необходимо создать файл TAB.
            out_file: Имя файла c расширением tab. Как вариант, можно использовать результат :meth:`suggest_tab_name`.
            override: Перезаписывать файл.
             Если установлено False и файл существует, будет выброшено исключение FileExistsError
            linked_file: Если файл генерируется для СУБД, и при установке значения True будет создан связанный файл

        Returns:
            Возвращает True, если успешно.

        Создание TAB файла для открытой таблицы или растра:

        .. literalinclude:: /../../tests/doc_examples/da/test_example_tabfile.py
            :pyobject: test_run_example_tabfile_gen
            :lines: 2-3, 7-
            :dedent: 4

        Создание TAB файла для открытого источника тайлового сервиса::

            prj_mercator = (
                'Earth Projection 10, 104, "m", 0 '
                'Bounds (-20037508.34, -20037508.34) (20037508.34, 20037508.34)'
            )
            osm_raster = axipy.provider_manager.tms.open(
                'http://maps.axioma-gis.ru/osm/{LEVEL}/{ROW}/{COL}.png',
                prj=prj_mercator
            )
            tab = axipy.TabFile()
            out_file_name = tab.suggest_tab_name(osm_raster)
            tab.generate_tab(osm_raster, out_file_name)

        Загрузка данных из БД PostgreSQL в виде связанной таблицы::

            definition = provider_manager.postgre.get_source(
                host='localhost',
                db_name='test',
                user='test',
                password='pass',
                dataobject='world'
            )
            table = provider_manager.open(definition)
            out_file_name = tab.suggest_tab_name(table)
            tab = TabFile()
            tab.generate_tab(table, out_file_name, linked_file = True)
        """

        fi = QFileInfo(out_file)
        if fi.exists() and not override:
            raise FileExistsError("File '{}' already exists".format(fi.absoluteFilePath()))
        params = {"linked": linked_file}
        return self._shadow.generateTab(data_object._shadow, fi, params)

    def suggest_tab_name(self, data_object: DataObject) -> str:
        """
        Сервисная функция.

        Предлагает наименование TAB файла для объекта данных.
        Результат можно использовать в методе :meth:`generate_tab` в качестве имени выходного файла.
        """
        return self._shadow.suggestTabName(data_object._shadow)
