"""
/***************************************************************************
 EditObsDialog
                                 A QGIS plugin
 Topaze
                             -------------------
        begin                : 2022-09-30
        git sha              : $Format:%H$
        copyright            : (C) 2022 by Jean-Marie ARSAC
        email                : jmarsac@arsac.wf
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os
from pathlib import Path

from PyQt5 import QtCore, QtWidgets, uic
from qgis.core import QgsProject

from topaze.__about__ import DIR_PLUGIN_ROOT
from topaze.bridge_lsci import BridgeLsci
from topaze.toolbelt import PlgLogger, PlgOptionsManager, PlgTranslator
from topaze.topaze_config import TopazeConfig
from topaze.topaze_utils import TopazeUtils

FORM_CLASS, _ = uic.loadUiType(
    os.path.join(os.path.dirname(__file__), "edit_obs_dialog.ui")
)


class EditObsDialog(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        """Constructor."""
        super(EditObsDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        self._obs_edited = False
        self._filter = None
        self._field_rows = None
        self._lsci = None
        self.radioButton_all.setChecked(True)
        self.radioButton_all.clicked.connect(self.on_radiobutton_all_clicked)
        self.radioButton_canvas.clicked.connect(self.on_radiobutton_canvas_clicked)
        self.radioButton_radiated_points.clicked.connect(
            self.on_radiobutton_radiated_points_clicked
        )
        self.radioButton_codification.clicked.connect(
            self.on_radiobutton_codification_clicked
        )

    def reset_widgets(self):
        self.comboBox_type_point.setEnabled(False)
        self.lineEdit_matricule.setEnabled(False)
        self.lineEdit_horizontal_angle.setEnabled(False)
        self.lineEdit_vertical_angle.setEnabled(False)
        self.lineEdit_sloped_distance.setEnabled(False)
        self.lineEdit_x.setEnabled(False)
        self.lineEdit_y.setEnabled(False)
        self.lineEdit_z.setEnabled(False)
        self.lineEdit_target_height.setEnabled(False)
        self.lineEdit_code.setEnabled(False)
        self.lineEdit_comment.setEnabled(False)

        self.comboBox_type_point.setVisible(False)
        self.lineEdit_matricule.setVisible(False)
        self.lineEdit_horizontal_angle.setVisible(False)
        self.lineEdit_vertical_angle.setVisible(False)
        self.lineEdit_sloped_distance.setVisible(False)
        self.lineEdit_x.setVisible(False)
        self.lineEdit_y.setVisible(False)
        self.lineEdit_z.setVisible(False)
        self.lineEdit_target_height.setVisible(False)
        self.lineEdit_code.setVisible(False)
        self.lineEdit_comment.setVisible(False)

        self.label_horizontal_angle.setVisible(False)
        self.label_vertical_angle.setVisible(False)
        self.label_sloped_distance.setVisible(False)
        self.label_x.setVisible(False)
        self.label_y.setVisible(False)
        self.label_z.setVisible(False)
        self.label_target_height.setVisible(False)
        self.label_code.setVisible(False)
        self.label_comment.setVisible(False)
        self.pushButton_export_lsci.setEnabled(False)

    def on_radiobutton_all_clicked(self):
        if self.buttonGroup_filter_obs.checkedButton():
            self._filter = "all"
            self.load_observations(self._field_rows, self._filter)
            self.pushButton_add.setEnabled(True)
            self.pushButton_change.setEnabled(True)
            self.pushButton_delete.setEnabled(True)
            self.pushButton_export_lsci.setEnabled(False)

    def on_radiobutton_canvas_clicked(self):
        if self.buttonGroup_filter_obs.checkedButton() and not self._obs_edited:
            self._filter = "canvas"
            self.load_observations(self._field_rows, self._filter)
            self.pushButton_add.setEnabled(False)
            self.pushButton_change.setEnabled(False)
            self.pushButton_delete.setEnabled(False)
            self.pushButton_export_lsci.setEnabled(False)
        else:
            self.radioButton_all.setChecked(True)
            self.pushButton_export_lsci.setEnabled(False)

    def on_radiobutton_radiated_points_clicked(self):
        if self.buttonGroup_filter_obs.checkedButton() and not self._obs_edited:
            self._filter = "points"
            self.load_observations(self._field_rows, self._filter)
            self.pushButton_add.setEnabled(False)
            self.pushButton_change.setEnabled(False)
            self.pushButton_delete.setEnabled(False)
            self.pushButton_export_lsci.setEnabled(False)
        else:
            self.radioButton_all.setChecked(True)
            self.pushButton_export_lsci.setEnabled(False)

    def on_radiobutton_codification_clicked(self):
        if self.buttonGroup_filter_obs.checkedButton() and not self._obs_edited:
            self._filter = "codification"
            self.load_observations(self._field_rows, self._filter)
            self.pushButton_add.setEnabled(False)
            self.pushButton_change.setEnabled(False)
            self.pushButton_delete.setEnabled(False)
            self.pushButton_export_lsci.setEnabled(True)
        else:
            self.radioButton_all.setChecked(True)
            self.pushButton_export_lsci.setEnabled(False)

    def load_observations(self, field_rows, filter: str = "all"):
        """load observations in dialog list

        :param field_rows: _description_
        :type field_rows: _type_
        :param filter: _description_, defaults to "all" ("canvas", "points", "codification")
        :type filter: str, optional
        """
        if filter == "codification" and not self._lsci:
            settings = self.settings = PlgOptionsManager().get_plg_settings()
            if settings.config_file:
                config_path = self.settings.config_file
        else:
            config_path = Path(DIR_PLUGIN_ROOT / "resources/settings" / "topaze.yml")
        config_dict = TopazeConfig.load_config(config_path)
        qlsc_file_path = str(
            Path(
                DIR_PLUGIN_ROOT
                / "resources/settings/lsci"
                / config_dict["codification"]["lsci"]
            )
        )
        self._lsci = BridgeLsci(qlsc_file_path)
        self._qlsc = self._lsci.qlsc()
        self.listWidget_observations.clear()
        if field_rows:
            if not self._field_rows:
                self._field_rows = field_rows
            if filter == "all":
                self.listWidget_observations.addItems(field_rows)
            else:
                hp = None
                pnt_codif = ""
                code = ""
                for i in range(0, len(field_rows)):
                    row = field_rows[i]
                    type = TopazeUtils.type_obs(row)
                    if type == "st":
                        hp = None
                    if filter == "canvas":
                        if type in ("st", "ref", "xyz", "hp"):
                            if type == "hp" and not hp:
                                hp = float(row[3:])
                                self.listWidget_observations.addItem(row)
                            elif type == "hp" and row[3:] != str(hp):
                                hp = float(row[3:])
                                self.listWidget_observations.addItem(row)
                            elif type == "xyz":
                                ty_obs, ty_pt = TopazeUtils.types_obs(row)
                                if ty_obs == "ref" or ty_obs == "st":
                                    self.listWidget_observations.addItem(row)
                            elif type != "hp":
                                self.listWidget_observations.addItem(row)
                    elif filter == "points":
                        if type in ("st", "ref", "pnt", "xyz", "hp", "hpp"):
                            if type == "hp" and not hp:
                                hp = float(row[3:])
                                self.listWidget_observations.addItem(row)
                            elif type == "hp" and row[3:] != str(hp):
                                hp = row["hp"]
                                self.listWidget_observations.addItem(row)
                            elif type != "hp":
                                self.listWidget_observations.addItem(row)
                    elif filter == "codification":
                        if type in ("pnt", "xyz", "code"):
                            if ((type == "pnt" or type == "xyz") and not pnt_codif) or (
                                (type == "pnt" or type == "xyz")
                                and pnt_codif
                                and "code" not in pnt_codif
                            ):
                                if "x=" in row:
                                    pnt_codif = row
                                else:
                                    pnt_codif = row[: row.index(" ")]
                            elif type == "code" and pnt_codif:
                                if code:
                                    code += " " + row
                                else:
                                    code = row
                                pnt_codif += " " + row
                                if row[5:6] == "2":
                                    nb = 2
                                else:
                                    nb = 1
                                self.listWidget_observations.addItem(pnt_codif)
                                pnt_codif = ""
                                for j in range(0, nb):
                                    row = field_rows[i + j]
                                    type = TopazeUtils.type_obs(row)
                                    if (
                                        type == "pnt" or type == "xyz"
                                    ) and not pnt_codif:
                                        if "x=" in row:
                                            pnt_codif = row
                                        else:
                                            pnt_codif = row[: row.index(" ")]
                                        pnt_codif += " " + code
                                        self.listWidget_observations.addItem(pnt_codif)
                                        pnt_codif = ""
                                i = j

    def update_combobox_types(self, type_obs, type_pt):
        self.comboBox_type_obs.setVisible(True)
        self.comboBox_type_obs.setEnabled(True)
        self.comboBox_type_obs.setCurrentText(type_obs)
        self.comboBox_type_obs.update()
        if type_obs == "xyz":
            if type_pt is not None:
                self.comboBox_type_point.setCurrentText(type_pt)
        else:
            self.comboBox_type_point.setCurrentText(type_pt)
        self.comboBox_type_point.update()

    def load_observation_fields(self, type_obs, values):
        if type_obs in ["st", "ref", "pnt", "xyz"]:
            if "pnt" in values:
                self.lineEdit_matricule.setText(values["pnt"])
            elif "st" in values:
                self.lineEdit_matricule.setText(values["st"])
            elif "ref" in values:
                self.lineEdit_matricule.setText(values["ref"])
            elif "xyz" in values:
                self.lineEdit_matricule.setText(values["xyz"])
            if type_obs == "st":
                if "hi" in values and values["hi"]:
                    self.lineEdit_instrument_height.setText(values["hi"])
                if "v0" in values and values["v0"]:
                    self.lineEdit_v0.setText(values["v0"])
            elif type_obs == "xyz":
                if "x" in values and values["x"]:
                    self.lineEdit_x.setText(values["x"])
                if "y" in values and values["y"]:
                    self.lineEdit_y.setText(values["y"])
                if "z" in values and values["z"]:
                    self.lineEdit_z.setText(values["z"])
            else:  # 'ref' or 'pnt'
                if "ah" in values and values["ah"]:
                    self.lineEdit_horizontal_angle.setText(values["ah"])
                if "av" in values and values["av"]:
                    self.lineEdit_vertical_angle.setText(values["av"])
                if "di" in values and values["di"]:
                    self.lineEdit_sloped_distance.setText(values["di"])
                if "hp" in values and values["hp"]:
                    self.lineEdit_target_height.setText(values["hp"])
        elif type_obs == "hp":
            if type_obs in values and values[type_obs]:
                self.lineEdit_target_height.setText(values[type_obs])
        elif type_obs == "code":
            if type_obs in values and values[type_obs]:
                self.lineEdit_code.setText(values["code"])
        elif type_obs == "rem":
            if type_obs in values and values[type_obs]:
                self.lineEdit_comment.setText(values["rem"])
        elif type_obs == "infos":
            if type_obs in values and values[type_obs]:
                self.lineEdit_infos.setText(values["infos"])

    def observation_fields_to_dict(self, type_obs, type_pt: str = None):
        dico = dict()
        if type_obs in ["st", "ref", "pnt", "xyz"]:
            if type_obs == "st":
                dico[type_obs] = self.lineEdit_matricule.text()
                dico["hi"] = self.lineEdit_instrument_height.text()
                s_val = self.lineEdit_v0.text()
                if s_val:
                    dico["v0"] = self.lineEdit_v0.text()
            elif type_obs == "xyz":
                if type_pt:
                    if type_pt == "S":
                        type_obs = "st"
                    elif type_pt == "R":
                        type_obs = "ref"
                    else:
                        type_obs = "pnt"
                else:
                    type_obs = "pnt"
                dico[type_obs] = self.lineEdit_matricule.text()
                dico["x"] = self.lineEdit_x.text()
                dico["y"] = self.lineEdit_y.text()
                s_val = self.lineEdit_z.text()
                if s_val:
                    dico["z"] = self.lineEdit_z.text()
            else:  # 'ref' or 'pnt'
                dico[type_obs] = self.lineEdit_matricule.text()
                s_val = self.lineEdit_horizontal_angle.text()
                if s_val:
                    dico["ah"] = self.lineEdit_horizontal_angle.text()
                s_val = self.lineEdit_vertical_angle.text()
                if s_val:
                    dico["av"] = self.lineEdit_vertical_angle.text()
                s_val = self.lineEdit_sloped_distance.text()
                if s_val:
                    dico["di"] = self.lineEdit_sloped_distance.text()
                s_val = self.lineEdit_target_height.text()
                if s_val:
                    dico["hp"] = self.lineEdit_target_height.text()
        elif type_obs == "hp":
            dico[type_obs] = self.lineEdit_target_height.text()
        elif type_obs == "code":
            dico[type_obs] = self.lineEdit_code.text()
        elif type_obs == "rem":
            dico["rem"] = self.lineEdit_comment.text()
        elif type_obs == "infos":
            dico["infos"] = self.lineEdit_infos.text()
        return dico

    def update_state_of_input_fields(self, type_obs, type_pt: str = None):
        # type_obs, type_pt = TopazeUtils.types_obs(row)
        # obs_dict = TopazeUtils.obs_str_to_dict(row)
        self.comboBox_type_point.setEnabled(False)
        self.comboBox_type_point.setVisible(False)

        self.lineEdit_matricule.setEnabled(False)
        self.lineEdit_instrument_height.setEnabled(False)
        self.lineEdit_v0.setEnabled(False)
        self.lineEdit_horizontal_angle.setEnabled(False)
        self.lineEdit_vertical_angle.setEnabled(False)
        self.lineEdit_sloped_distance.setEnabled(False)
        self.lineEdit_x.setEnabled(False)
        self.lineEdit_y.setEnabled(False)
        self.lineEdit_z.setEnabled(False)
        self.lineEdit_target_height.setEnabled(False)
        self.lineEdit_code.setEnabled(False)
        self.lineEdit_comment.setEnabled(False)
        self.lineEdit_infos.setEnabled(False)

        self.lineEdit_matricule.setVisible(False)
        self.lineEdit_instrument_height.setVisible(False)
        self.lineEdit_v0.setVisible(False)
        self.lineEdit_horizontal_angle.setVisible(False)
        self.lineEdit_vertical_angle.setVisible(False)
        self.lineEdit_sloped_distance.setVisible(False)
        self.lineEdit_x.setVisible(False)
        self.lineEdit_y.setVisible(False)
        self.lineEdit_z.setVisible(False)
        self.lineEdit_target_height.setVisible(False)
        self.lineEdit_code.setVisible(False)
        self.lineEdit_comment.setVisible(False)
        self.lineEdit_infos.setVisible(False)

        self.label_instrument_height.setVisible(False)
        self.label_v0.setVisible(False)
        self.label_horizontal_angle.setVisible(False)
        self.label_vertical_angle.setVisible(False)
        self.label_sloped_distance.setVisible(False)
        self.label_target_height.setVisible(False)
        self.label_x.setVisible(False)
        self.label_y.setVisible(False)
        self.label_z.setVisible(False)
        self.label_code.setVisible(False)
        self.label_comment.setVisible(False)
        self.label_infos.setVisible(False)
        if type_obs in ["st", "ref", "pnt", "xyz"]:
            self.lineEdit_matricule.setVisible(True)
            self.lineEdit_matricule.setEnabled(True)
            if type_obs == "st":
                self.label_instrument_height.setVisible(True)
                self.label_v0.setVisible(True)
                self.lineEdit_instrument_height.setVisible(True)
                self.lineEdit_v0.setVisible(True)
                self.lineEdit_instrument_height.setEnabled(True)
                self.lineEdit_v0.setEnabled(True)
            elif type_obs == "xyz":
                self.comboBox_type_point.setEnabled(True)
                self.comboBox_type_point.setVisible(True)
                if type_pt is not None:
                    self.comboBox_type_point.setCurrentText(type_pt)
                self.label_x.setVisible(True)
                self.label_y.setVisible(True)
                self.label_z.setVisible(True)
                self.lineEdit_x.setVisible(True)
                self.lineEdit_y.setVisible(True)
                self.lineEdit_z.setVisible(True)
                self.lineEdit_x.setEnabled(True)
                self.lineEdit_y.setEnabled(True)
                self.lineEdit_z.setEnabled(True)
            else:  # "ref" or "pnt"
                self.label_horizontal_angle.setVisible(True)
                self.label_vertical_angle.setVisible(True)
                self.label_sloped_distance.setVisible(True)
                self.label_target_height.setVisible(True)
                self.lineEdit_horizontal_angle.setVisible(True)
                self.lineEdit_vertical_angle.setVisible(True)
                self.lineEdit_sloped_distance.setVisible(True)
                self.lineEdit_horizontal_angle.setEnabled(True)
                self.lineEdit_vertical_angle.setEnabled(True)
                self.lineEdit_sloped_distance.setEnabled(True)
                self.lineEdit_target_height.setEnabled(True)
                self.lineEdit_target_height.setVisible(True)
        elif type_obs == "hp":
            self.label_target_height.setEnabled(True)
            self.lineEdit_target_height.setEnabled(True)
            self.lineEdit_target_height.setVisible(True)
        elif type_obs == "code":
            self.label_code.setEnabled(True)
            self.lineEdit_code.setEnabled(True)
            self.lineEdit_code.setVisible(True)
        elif type_obs == "rem":
            self.label_comment.setEnabled(True)
            self.lineEdit_comment.setEnabled(True)
            self.lineEdit_comment.setVisible(True)
        elif type_obs == "infos":
            self.label_infos.setEnabled(True)
            self.lineEdit_infos.setEnabled(True)
            self.lineEdit_infos.setVisible(True)
