from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

import axipy
from PySide2.QtCore import Qt, Slot
from PySide2.QtWidgets import QDialog, QPushButton, QWidget
from .observer import MergePolygonsObserver
from .ui import Ui_Dialog
from .utils import get_fields_names
from .worker import Worker

if TYPE_CHECKING:
    from .__init__ import MergePolygons

__all__ = [
    "Dialog",
]


class Dialog(QDialog, Ui_Dialog):

    def __init__(self, plugin: 'MergePolygons', *args, **kwargs) -> None:
        super().__init__(*args, **kwargs, parent=axipy.view_manager.global_parent)
        self._plugin: 'MergePolygons' = plugin

        self.setupUi(self)
        self.setAttribute(Qt.WA_DeleteOnClose, True)

        active_table_names: tuple[str, ...] = tuple(
            t.name for t in MergePolygonsObserver.get_tables_from_active_map_view())
        selection_table = axipy.data_manager.selection
        if selection_table is not None and selection_table.base_table.name in active_table_names:
            self.cbox_inp_table.addItem(selection_table.name)
        self.cbox_inp_table.addItems(active_table_names)
        self.cbox_inp_table.currentTextChanged.connect(self.slot_cbox_inp_table_text_changed)

        self.slot_cbox_inp_table_text_changed(self.cbox_inp_table.currentText())

        self.tb_choose_save_file_name.clicked.connect(self.slot_choose_save_file_name)

        self.pbar.setHidden(True)
        self._ok_button.setText(self._plugin.tr("Объединить"))
        self._ok_button.setEnabled(False)

    @property
    def _ok_button(self) -> QPushButton:
        return self.buttonBox.button(self.buttonBox.Ok)

    @property
    def _cancel_button(self) -> QPushButton:
        return self.buttonBox.button(self.buttonBox.Cancel)

    def _block_gui(self) -> None:
        enabled_widgets = (self.pbar, self.buttonBox, self._cancel_button)
        for child in self.findChildren(QWidget):
            if child in enabled_widgets:
                continue
            child.setEnabled(False)

    def done(self, return_code: int) -> None:
        if return_code == self.Accepted:
            inp_table_name: str = self.cbox_inp_table.currentText()
            cbox = self.cbox_field_name
            field_name: str | None = None
            if cbox.currentIndex() != -1:
                field_name = cbox.currentText()
            out_table_path = Path(self.le_out_table_path.text())
            worker = Worker(
                self._plugin,
                inp_table_name,
                field_name,
                out_table_path,
            )
            worker.range_changed.connect(self.slot_pbar_range_changed)
            worker.value_changed.connect(self.slot_pbar_set_value)
            self._cancel_button.clicked.connect(worker.cancel)

            self._block_gui()
            self.pbar.setHidden(False)

            worker.run_and_get()
            if worker.is_canceled:
                return None

        super().done(return_code)

    @Slot()
    def slot_choose_save_file_name(self) -> None:
        result = axipy.save_file_dialog(filter_arg="MapInfo Tab (*.tab)")
        if result:
            self.le_out_table_path.setText(str(result))
            self._ok_button.setEnabled(True)

    @Slot(axipy.Task.Range)
    def slot_pbar_range_changed(self, task_range: axipy.Task.Range) -> None:
        self.pbar.setRange(task_range.min, task_range.max)

    @Slot(int)
    def slot_pbar_set_value(self, value: int) -> None:
        self.pbar.setValue(value)

    @Slot(str)
    def slot_cbox_inp_table_text_changed(self, text: str) -> None:
        table = axipy.data_manager.find(text)
        fields_names = get_fields_names(table)
        self.cbox_field_name.clear()
        self.cbox_field_name.addItems(fields_names)
        self.cbox_field_name.setCurrentIndex(-1)
