"""
Класс страницы wizard для заполнения параметров открытия.
"""
from typing import Dict

from PySide2.QtCore import Qt, Slot, QLocale
from PySide2.QtGui import QDoubleValidator
from PySide2.QtWidgets import QWizardPage, QVBoxLayout, QLabel, QPushButton, QLineEdit, QDialog, QGroupBox, QComboBox, \
    QScrollArea, QFormLayout, QGridLayout
from axipy import CoordSystem, ChooseCoordSystemDialog, tr, FloatCoord

from .. import helper
from .. import wizardconverter
from ..json_pkg import jsonloader

ogr_arc_stepsize_name = "ogr_arc_stepsize"
ogr_arc_max_gap_name = "ogr_arc_max_gap"

gbox_encoding_name = "gbox_encoding"
gbox_approx_name = "gbox_approx"


class OpenSettingsPage(QWizardPage):
    """
    Страница выбора входной СК и параметров открытия входных файлов.
    """

    def __init__(self, wizard) -> None:
        super().__init__()

        self.wzrd = wizard  # type: wizardconverter.WizardConverter

        # Вертикальная разметка страницы
        self.vbox = QVBoxLayout()
        self.setLayout(self.vbox)

        label = QLabel(tr("Формат входных файлов"))
        label.setStyleSheet("font-weight: bold")
        self.inp_format_label = QLabel()
        self.vbox.addWidget(label)
        self.vbox.addWidget(self.inp_format_label)

        # Заголовок СК
        title_label = QLabel(tr("Входная система координат"))
        title_label.setStyleSheet("font-weight: bold")
        self.vbox.addWidget(title_label)

        # Отображение и выбор СК
        self.line_edit = QLineEdit()
        self.line_edit.setReadOnly(True)
        btn = QPushButton("...", clicked=self.choose_in_coord, objectName="btn_choose_in_coord")
        btn.setMaximumWidth(20)
        hbox = helper.create_hbox(self.line_edit, btn)
        hbox.setAlignment(Qt.AlignLeft)
        self.vbox.addLayout(hbox)

        self.form_view = None

    def initializePage(self) -> None:
        """
        Инициализация страницы. Считывание входной СК и загрузка формы для определенного входного формата gdal
        и для настроек открытия.
        """
        # Синхронизация с внутр. значением при инициализации страницы
        self.inp_format_label.setText("{}".format(self.wzrd.drivers[self.wzrd.inp_gdal_format]["name"]))
        btn = self.findChild(QPushButton, "btn_choose_in_coord")
        if self.wzrd.inp_cs:
            self.line_edit.setText(self.wzrd.inp_cs.name)
            btn.setEnabled(True)
        else:
            self.line_edit.setText(tr("Входной формат не поддерживает систему координат."))
            btn.setEnabled(False)

        # Загрузка и добавление формы с параметрами открытия
        if self.wzrd.inp_gdal_format == "DXF":
            # Добавление параметра без json, чтобы не было надписи, что у драйвера нет параметров,
            # т.к. они будут добавлены отдельно
            add_param_later = True
        else:
            add_param_later = False
        self.form_view = jsonloader.get_form_view(
            self, self.wzrd.inp_gdal_format, ["open_options"], add_param_later=add_param_later)
        self.vbox.addWidget(self.form_view)

        if add_param_later:
            self.add_dxf_encoding()
            self.add_dxf_approx()

    def cleanupPage(self) -> None:
        """
        Вызывается при нажатии кнопки назад. Удаляет добавленную форму.
        """
        if self.form_view is not None:
            self.form_view.setParent(None)

    def validatePage(self) -> True:
        """
        Считывает польз. ввод с формы при нажатии кнопки далее.
        """
        form = self.form_view.widget()
        self.wzrd.open_options, _, _ = jsonloader.read_form(form, self.wzrd.inp_gdal_format, self.wzrd)

        if self.wzrd.inp_gdal_format == "DXF":
            gbox: QGroupBox = self.findChild(QScrollArea).widget().findChild(QGroupBox, gbox_encoding_name)
            if gbox.isChecked():
                cbox: QComboBox = gbox.findChild(QComboBox)
                cbox_text = cbox.currentText()
                values: Dict[str, str] = self.get_dxf_values()
                i = tuple(values.values()).index(cbox_text)
                k = tuple(values.keys())[i]
                self.wzrd.gdal_config_options["DXF_ENCODING"] = k

            gbox: QGroupBox = self.findChild(QScrollArea).widget().findChild(QGroupBox, gbox_approx_name)
            if gbox.isChecked():
                le: QLineEdit = gbox.findChild(QLineEdit, ogr_arc_stepsize_name)
                cbox_text = le.text()
                self.wzrd.gdal_config_options["OGR_ARC_STEPSIZE"] = self.format_float_for_gdal_config(cbox_text)

                le: QLineEdit = gbox.findChild(QLineEdit, ogr_arc_max_gap_name)
                cbox_text = le.text()
                self.wzrd.gdal_config_options["OGR_ARC_MAX_GAP"] = self.format_float_for_gdal_config(cbox_text)

        return True

    @staticmethod
    def format_float_for_gdal_config(value: str) -> str:
        return FloatCoord(value).as_string(locale=QLocale.English)

    @Slot()
    def choose_in_coord(self) -> None:
        """
        Выбор входной СК при нажатии кнопки "...".
        """
        # Обработка декартовых СК
        if self.wzrd.inp_cs.non_earth:
            cs = CoordSystem.from_wkt(self.wzrd.inp_cs.wkt)
        else:
            cs = CoordSystem.from_proj(self.wzrd.inp_cs.proj)

        # Диалог выбора СК
        dlg = ChooseCoordSystemDialog(cs)
        dlg.setModal(True)
        if dlg.exec_() == QDialog.Accepted:
            cs = dlg.chosenCoordSystem()
            self.wzrd.inp_cs = cs
            self.line_edit.setText(self.wzrd.inp_cs.name)

    def add_dxf_encoding(self) -> None:
        gbox = QGroupBox()
        gbox.setObjectName(gbox_encoding_name)
        gbox.setTitle("Переопределить кодировку DXF")
        gbox.setCheckable(True)
        gbox.setChecked(False)
        vbox = QVBoxLayout()
        gbox.setLayout(vbox)

        cbox = QComboBox()
        values: Dict[str, str] = self.get_dxf_values()
        cbox.addItems(values.values())

        vbox.addWidget(cbox)

        form: QFormLayout = self.findChild(QScrollArea).widget().layout()
        form.addWidget(gbox)

    def add_dxf_approx(self) -> None:
        gbox = QGroupBox()
        gbox.setObjectName(gbox_approx_name)
        gbox.setTitle("Переопределить аппроксимацию дуг и окружностей")
        gbox.setCheckable(True)
        gbox.setChecked(False)
        vbox = QVBoxLayout()
        gbox.setLayout(vbox)

        label = QLabel("Ставить узел каждые:")
        vbox.addWidget(label)

        grid = QGridLayout()
        le_ogr_arc_stepsize = QLineEdit()
        le_ogr_arc_stepsize.setObjectName(ogr_arc_stepsize_name)
        v = QDoubleValidator()
        v.setBottom(0)
        le_ogr_arc_stepsize.setValidator(v)
        le_ogr_arc_stepsize.setText("4")
        grid.addWidget(le_ogr_arc_stepsize, 0, 0)
        grid.addWidget(QLabel("градусов"), 0, 1)

        le_ogr_arc_max_gap = QLineEdit()
        le_ogr_arc_max_gap.setObjectName(ogr_arc_max_gap_name)
        v = QDoubleValidator()
        v.setBottom(0)
        le_ogr_arc_max_gap.setValidator(v)
        le_ogr_arc_max_gap.setText("0")
        grid.addWidget(le_ogr_arc_max_gap, 1, 0)
        grid.addWidget(QLabel("единиц измерения"), 1, 1)

        vbox.addLayout(grid)

        form: QFormLayout = self.findChild(QScrollArea).widget().layout()
        form.addWidget(gbox)

    def get_dxf_values(self) -> Dict[str, str]:
        values_dict: Dict[str, str] = self.wzrd.drivers["MapInfo File"]["layer"]["ENCODING"]["values"]

        keys = list(values_dict.keys())
        values = list(values_dict.values())
        keys.insert(0, "UTF-8")
        values.insert(0, "UTF-8")
        values_dict = dict(elem for elem in zip(keys, values))
        return values_dict
