# -*- coding: utf-8 -*-
"""
/***************************************************************************
Name                 : Mascaret
Description          : Pre and Postprocessing for Mascaret for QGIS
Date                 : December,2017
copyright            : (C) 2017 by Artelia
email                :
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""
import os

import numpy as np
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import *
from qgis.PyQt.uic import *
from qgis.core import *
from qgis.gui import *
from qgis.utils import *
from shapely.geometry import Point

from .FctDialog import ctrl_set_value, ctrl_get_value, fill_qcombobox
# Widgets Buse
from .MetBordaBuWidget import MetBordaBuWidget
# Widgets Dalot
from .MetBordaDaWidget import MetBordaDaWidget
# Widgets Pont arche
from .MetBordaPaWidget import MetBordaPaWidget
from .MetBordaPcWidget import MetBordaPcWidget
# Widgets Pont cadre
from .MetBradleyPcWidget import MetBradleyPcWidget
from .MetOrificeBuWidget import MetOrificeBuWidget
from .MetOrificeDaWidget import MetOrificeDaWidget
from .MetOrificePaWidget import MetOrificePaWidget
from .MetOrificePcWidget import MetOrificePcWidget
# FloodGate
from .StructureFgDialog import StructureFgDialog
from ..ClassLaws import ClassLaws
from ..ClassMethod import ClassMethod
from ..ClassTableStructure import ClassTableStructure, update_etat_struct


class ClassStructureEditDialog(QDialog):
    def __init__(self, mgis, id_struct):
        QDialog.__init__(self)
        self.mgis = mgis
        self.mdb = self.mgis.mdb
        self.tbst = ClassTableStructure()
        self.clmeth = ClassMethod(self.mgis)
        self.wgt_met = QWidget()

        self.met_calc = None
        self.meth = None

        self.param_meth_calc = {
            "PC": {
                0: {"wgt": MetBradleyPcWidget, "wgt_param": [self.mgis, "72", id_struct]},
                1: {"wgt": MetBordaPcWidget, "wgt_param": [self.mgis, id_struct]},
                3: {"wgt": MetOrificePcWidget, "wgt_param": [self.mgis, id_struct]},
                4: {"wgt": MetBradleyPcWidget, "wgt_param": [self.mgis, "78", id_struct]},
            },
            "PA": {
                1: {"wgt": MetBordaPaWidget, "wgt_param": [self.mgis, id_struct]},
                3: {"wgt": MetOrificePaWidget, "wgt_param": [self.mgis, id_struct]},
            },
            "DA": {
                1: {"wgt": MetBordaDaWidget, "wgt_param": [self.mgis, id_struct]},
                3: {"wgt": MetOrificeDaWidget, "wgt_param": [self.mgis, id_struct]},
            },
            "BU": {
                1: {"wgt": MetBordaBuWidget, "wgt_param": [self.mgis, id_struct]},
                3: {"wgt": MetOrificeBuWidget, "wgt_param": [self.mgis, id_struct]},
            },
        }

        self.id_struct = id_struct
        self.current_meth = 0
        self.lst_meth_calc = []
        self.ui = loadUi(os.path.join(self.mgis.masplugPath, "ui/ui_structure_edit.ui"), self)

        self.cb_met_calc.currentIndexChanged[int].connect(self.change_met_calc)
        self.b_ok.accepted.connect(self.accept_page)
        self.b_ok.rejected.connect(self.reject_page)
        self.b_up_prof.clicked.connect(self.update_profil)
        self.b_up_prof.setIcon(
            QIcon(os.path.join(self.mgis.masplugPath, "Structure/images/update.png"))
        )
        self.dico_ctrl_fg = None

        if id_struct:
            self.is_loading = True
            sql = (
                "SELECT name, type, method, active, id_prof_ori,comment, zbreak, erase_flag FROM {0}.struct_config "
                "WHERE id = {1}".format(self.mdb.SCHEMA, self.id_struct)
            )
            rows = self.mdb.run_query(sql, fetch=True)
            self.id_prof_ori = rows[0][4]
            self.typ_struct = rows[0][1]

            for m in self.tbst.dico_struc_typ[self.typ_struct]["meth_calc"]:
                self.lst_meth_calc.append([m, self.tbst.dico_meth_calc[m]])

            self.lbl_type.setText(self.tbst.dico_struc_typ[self.typ_struct]["name"])
            self.txt_name.setText(rows[0][0])
            self.txt_comm.setText(rows[0][5])
            self.cc_active.setChecked(rows[0][3])
            self.ch_bperm.setChecked(rows[0][7])
            self.dbs_zbreak.setValue(rows[0][6])

            if not self.mgis.cond_api:
                self.ch_bperm.setEnabled(False)
                self.dbs_zbreak.setEnabled(False)
                self.label_info.show()
            else:
                self.ch_bperm.setEnabled(True)
                self.dbs_zbreak.setEnabled(True)
                self.label_info.hide()
            fill_qcombobox(self.cb_met_calc, self.lst_meth_calc, val_def=rows[0][2])
            self.is_loading = False

            rows = self.mdb.run_query(
                "SELECT gid FROM {0}.profiles".format(self.mdb.SCHEMA), fetch=True
            )

            list_p = [v[0] for v in rows]
            if self.id_prof_ori in list_p:
                self.b_up_prof.setEnabled(True)
            else:
                self.b_up_prof.setEnabled(False)

            # floodgate
            self.init_gui_fg()

    def update_profil(self):
        """
        update zx of profil
        """
        tab = {"x": [], "z": []}
        where = "gid = '{0}' ".format(self.id_prof_ori)
        feature = self.mdb.select(
            "profiles", where=where, list_var=["x", "z", "abscissa", "branchnum"]
        )
        tab["x"] = [float(var) for var in feature["x"][0].split()]
        tab["z"] = [float(var) for var in feature["z"][0].split()]

        if len(tab["x"]) == 0 or len(tab["z"]) == 0:
            self.mgis.add_info("Check if the profile is saved.")
            return

        colonnes = ["id_config", "id_order", "x", "z"]
        xz = list(zip(tab["x"], tab["z"]))
        values = []
        for order, (x, z) in enumerate(xz):
            values.append([self.id_struct, order, x, z])

        self.mdb.delete("profil_struct", where="id_config = {}".format(self.id_struct))
        self.mdb.insert_res("profil_struct", values, colonnes)
        absc = feature["abscissa"][0]
        tab = {self.id_struct: {"abscissa": absc}}
        self.mdb.update("struct_config", tab, var="id")

    def change_met_calc(self):
        if not self.is_loading:
            if (
                    QMessageBox.question(
                        self,
                        "Warning",
                        "Save current parameters ?",
                        QMessageBox.Cancel | QMessageBox.Ok,
                    )
            ) == QMessageBox.Ok:
                self.save_struct()
        self.txt_name.setFocus()
        self.met_calc = self.cb_met_calc.itemData(self.cb_met_calc.currentIndex())
        self.display_fg()
        param = self.param_meth_calc[self.typ_struct][self.met_calc]
        self.wgt_met = param["wgt"](*param["wgt_param"])
        self.sw_input.addWidget(self.wgt_met)
        self.sw_input.setCurrentIndex(1)
        self.sw_input.removeWidget(self.sw_input.widget(0))
        self.display_param_struct()

    def display_param_struct(self):
        sql = "SELECT var, value FROM {0}.struct_param " "WHERE id_config = {1}".format(
            self.mdb.SCHEMA, self.id_struct
        )
        rows = self.mdb.run_query(sql, fetch=True)
        for param, val in rows:
            if param in self.wgt_met.dico_ctrl.keys():
                ctrls = self.wgt_met.dico_ctrl[param]
                for ctrl in ctrls:
                    if param == "FORMPIL":
                        val = str(val).replace(".", "_").replace("_0", "")
                    ctrl_set_value(ctrl, val)

        for tab, param in self.wgt_met.dico_tab.items():
            # tab.setRowCount(0)
            t = param["type"]
            sql = (
                "SELECT id_elem FROM {0}.struct_elem "
                "WHERE id_config = {1} AND type = {2} ORDER BY id_elem".format(
                    self.mdb.SCHEMA, self.id_struct, t
                )
            )
            elems = self.mdb.run_query(sql, fetch=True)

            for r, elem in enumerate(elems):
                # tab.insertRow(r)
                for c, col in enumerate(param["col"]):
                    sql = (
                        "SELECT value FROM {0}.struct_elem_param WHERE id_config = {1} "
                        "AND id_elem = {2} and var = '{3}'".format(
                            self.mdb.SCHEMA, self.id_struct, elem[0], col["fld"]
                        )
                    )
                    row = self.mdb.run_query(sql, fetch=True)
                    if len(row) > 0:
                        val = row[0][0]
                    else:
                        val = ctrl_get_value(col["valdef"])

                    if col["fld"] == "FORMPIL":
                        val = str(val).replace(".", "_").replace("_0", "")

                    if col["cb"]:
                        cb = tab.cellWidget(r, c)
                        ctrl_set_value(cb, val)
                    else:
                        itm = tab.item(r, c)
                        itm.setData(0, val)

            tab.hide()
            tab.resizeColumnsToContents()
            tab.resizeRowsToContents()
            tab.show()

    def accept_page(self):
        # save Info
        if self.save_struct():
            self.clmeth.create_poly_elem(self.id_struct, self.typ_struct)
            active = self.cc_active.isChecked()
            if active:
                self.sav_meth(self.id_struct, self.current_meth, self.wgt_met)
            update_etat_struct(self.mdb)
            self.accept()
            # else:
            #     self.reject_page()

    def save_struct(self):
        self.current_meth = self.cb_met_calc.itemData(self.cb_met_calc.currentIndex())
        if self.typ_struct == "PC":
            verif, msg = self.verif_pc(self.id_struct)
        elif self.typ_struct == "PA":
            verif, msg = self.verif_pa(self.id_struct)
        elif self.typ_struct == "DA":
            verif, msg = self.verif_da(self.id_struct)
        elif self.typ_struct == "BU":
            verif, msg = self.verif_bu(self.id_struct)
        else:
            verif, msg = True, ""

        if verif:
            name = str(self.txt_name.text())
            comm = str(self.txt_comm.toPlainText())
            active = self.cc_active.isChecked()
            zbreak = self.dbs_zbreak.value()
            bperm = self.ch_bperm.isChecked()
            if active:
                sql = "SELECT id_prof_ori FROM {0}.struct_config WHERE id = {1}".format(
                    self.mdb.SCHEMA, self.id_struct
                )
                row = self.mdb.run_query(sql, fetch=True)
                id_profil = row[0][0]
                sql = "UPDATE {0}.struct_config SET active = FALSE WHERE id_prof_ori = {1}".format(
                    self.mdb.SCHEMA, id_profil
                )
                self.mdb.execute(sql)

            sql = (
                "UPDATE {0}.struct_config SET name = '{2}', method = {3}, active = {4}, comment= '{5}', "
                "zbreak = {6}, erase_flag = {7} WHERE id = {1}".format(
                    self.mdb.SCHEMA, self.id_struct, name, self.current_meth, active, comm, zbreak, bperm
                )
            )
            self.mdb.execute(sql)

            sql = "DELETE FROM {0}.struct_elem WHERE id_config = {1}".format(
                self.mdb.SCHEMA, self.id_struct
            )
            self.mdb.execute(sql)
            sql = "DELETE FROM {0}.struct_elem_param WHERE id_config = {1}".format(
                self.mdb.SCHEMA, self.id_struct
            )
            self.mdb.execute(sql)

            for var, ctrls in self.wgt_met.dico_ctrl.items():
                if var == "FORMPIL":
                    val = float(ctrl_get_value(ctrls[0]).replace("_", "."))
                else:
                    val = float(ctrl_get_value(ctrls[0]))

                sql = "SELECT * FROM {0}.struct_param WHERE id_config = {1} AND var = '{2}'".format(
                    self.mdb.SCHEMA, self.id_struct, var
                )
                row = self.mdb.run_query(sql, fetch=True)
                if len(row) > 0:
                    sql = "UPDATE {0}.struct_param SET value = {3} WHERE id_config = {1} AND var = '{2}'".format(
                        self.mdb.SCHEMA, self.id_struct, var, val
                    )
                    self.mdb.execute(sql)
                else:
                    sql = "INSERT INTO {0}.struct_param (id_config, var, value) VALUES ({1}, '{2}', {3})".format(
                        self.mdb.SCHEMA, self.id_struct, var, val
                    )
                    self.mdb.execute(sql)

            for tab, param in self.wgt_met.dico_tab.items():
                type_elem = param["type"]
                for r in range(tab.rowCount()):
                    id_elem = eval(param["id"].format(r))
                    sql = "INSERT INTO {0}.struct_elem (id_config, id_elem, type) VALUES ({1}, {2}, {3})".format(
                        self.mdb.SCHEMA, self.id_struct, id_elem, type_elem
                    )
                    self.mdb.execute(sql)
                    for c, col in enumerate(param["col"]):
                        var = col["fld"]
                        if col["cb"]:
                            cb = tab.cellWidget(r, c)
                            val = cb.itemData(cb.currentIndex())
                            if var == "FORMPIL":
                                val = val.replace("_", ".")
                        else:
                            itm = tab.item(r, c)
                            val = itm.data(0)
                        if val is None:
                            val = "Null"
                        sql = (
                            "INSERT INTO {0}.struct_elem_param (id_config, id_elem, var, value) "
                            "VALUES ({1}, {2}, '{3}', {4})".format(
                                self.mdb.SCHEMA, self.id_struct, id_elem, var, val
                            )
                        )
                        self.mdb.execute(sql)

            return True
        else:
            msg_txt = "Erreurs lor de la construction de la structure :"
            for m in msg:
                msg_txt += "\n- {}".format(m)
            QMessageBox.warning(self, "Error", msg_txt)
            return False

    def reject_page(self):
        self.mgis.add_info("Cancel of Structure", dbg=True)
        self.reject()

    def verif_pc(self, id_struct):
        valid, msg = True, []

        v, m = self.verif_exist_trav()
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_bas_tablier(id_struct)
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_larg_struct(id_struct)
        if not v:
            valid = False
            msg.append(m)

        return valid, msg

    def verif_pa(self, id_struct):
        valid, msg = True, []

        v, m = self.verif_exist_trav()
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_haut_tablier(id_struct)
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_larg_struct(id_struct)
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_z_arche()
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_arche_tab()
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_arche_profil(id_struct)
        if not v:
            valid = False
            msg.append(m)

        return valid, msg

    def verif_da(self, id_struct):
        valid, msg = True, []

        v, m = self.verif_exist_trav()
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_haut_tablier(id_struct)
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_larg_struct(id_struct)
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_radier_tab()
        if not v:
            valid = False
            msg.append(m)

        return valid, msg

    def verif_bu(self, id_struct):
        valid, msg = True, []

        v, m = self.verif_exist_trav()
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_haut_tablier(id_struct)
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_buse_tab()
        if not v:
            valid = False
            msg.append(m)

        v, m = self.verif_buse_intersect()
        if not v:
            valid = False
            msg.append(m)

        return valid, msg

    def verif_exist_trav(self):
        if ctrl_get_value(self.wgt_met.dico_ctrl["NBTRAVE"][0]) < 1.0:
            return False, "Aucune travee de saisie"
        else:
            return True, None

    def verif_haut_tablier(self, id_struct):
        sql = "SELECT MIN(z) FROM {0}.profil_struct WHERE id_config = {1}".format(
            self.mdb.SCHEMA, id_struct
        )
        rows = self.mdb.run_query(sql, fetch=True)
        profil_z_min = rows[0][0]

        cote_tablier = ctrl_get_value(self.wgt_met.dico_ctrl["ZTOPTAB"][0])
        if cote_tablier <= profil_z_min:
            return False, "La cote du tablier est inferieure à la cote minimum du profil"
        else:
            return True, None

    def verif_bas_tablier(self, id_struct):
        sql = "SELECT MIN(z) FROM {0}.profil_struct WHERE id_config = {1}".format(
            self.mdb.SCHEMA, id_struct
        )
        rows = self.mdb.run_query(sql, fetch=True)
        profil_z_min = rows[0][0]

        cote_bas_tablier = ctrl_get_value(self.wgt_met.dico_ctrl["ZTOPTAB"][0]) - ctrl_get_value(
            self.wgt_met.dico_ctrl["EPAITAB"][0]
        )
        if cote_bas_tablier <= profil_z_min:
            return False, "La cote du bas du tablier est inferieure à la cote minimum du profil"
        else:
            return True, None

    def verif_larg_struct(self, id_struct):
        for v, var in enumerate(self.wgt_met.dico_tab[self.wgt_met.tab_trav]["col"]):
            if var["fld"] == "LARGTRA":
                col_trav = v
                break

        for v, var in enumerate(self.wgt_met.dico_tab[self.wgt_met.tab_pile]["col"]):
            if var["fld"] == "LARGPIL":
                col_pile = v
                break

        sql = "SELECT MAX(x) FROM {0}.profil_struct WHERE id_config = {1}".format(
            self.mdb.SCHEMA, id_struct
        )
        rows = self.mdb.run_query(sql, fetch=True)
        profil_x_max = rows[0][0]

        x_fin = ctrl_get_value(self.wgt_met.dico_ctrl["FIRSTWD"][0])
        for r in range(self.wgt_met.tab_trav.rowCount()):
            itm = self.wgt_met.tab_trav.item(r, col_trav)
            x_fin += itm.data(0)
        for r in range(self.wgt_met.tab_pile.rowCount()):
            itm = self.wgt_met.tab_pile.item(r, col_pile)
            x_fin += itm.data(0)

        if x_fin > profil_x_max:
            return False, "La largeur totale de la structure est superieure a la largeur du profil"
        else:
            return True, None

    def verif_z_arche(self):
        arche_err = []
        for r in range(self.wgt_met.tab_trav.rowCount()):
            forme_arche = ctrl_get_value(self.wgt_met.tab_trav.cellWidget(r, 0))
            if forme_arche == 2:
                if self.wgt_met.tab_trav.item(r, 2).data(0) >= self.wgt_met.tab_trav.item(
                        r, 3
                ).data(0):
                    arche_err.append(r + 1)

        if len(arche_err) > 0:
            txt_arche = ""
            for arche in arche_err:
                txt_arche += "{}, ".format(arche)
            return False, "Arche(s) {} : Z haut <= Z bas".format(txt_arche[:-2])
        else:
            return True, None

    def verif_arche_tab(self):
        arche_err = []
        cote_tablier = ctrl_get_value(self.wgt_met.dico_ctrl["ZTOPTAB"][0])
        for r in range(self.wgt_met.tab_trav.rowCount()):
            forme_arche = ctrl_get_value(self.wgt_met.tab_trav.cellWidget(r, 0))
            if forme_arche == 1:
                z_top = self.wgt_met.tab_trav.item(r, 2).data(0) + (
                        self.wgt_met.tab_trav.item(r, 1).data(0) / 2
                )
            elif forme_arche == 2:
                z_top = self.wgt_met.tab_trav.item(r, 3).data(0)
            if z_top >= cote_tablier:
                arche_err.append(r + 1)

        if len(arche_err) > 0:
            txt_arche = ""
            for arche in arche_err:
                txt_arche += "{}, ".format(arche)
            return False, "Arche(s) {} : Z haut >= Cote du haut du tablier".format(txt_arche[:-2])
        else:
            return True, None

    def verif_arche_profil(self, id_struct):
        arche_err = []
        x_tmp = ctrl_get_value(self.wgt_met.dico_ctrl["FIRSTWD"][0])
        nb_arche = ctrl_get_value(self.wgt_met.dico_ctrl["NBTRAVE"][0])

        for r in range(self.wgt_met.tab_trav.rowCount()):
            larg = self.wgt_met.tab_trav.item(r, 1).data(0)
            if r not in [0, nb_arche - 1]:
                forme_arche = ctrl_get_value(self.wgt_met.tab_trav.cellWidget(r, 0))
                if forme_arche == 1:
                    z_top = self.wgt_met.tab_trav.item(r, 2).data(0) + (
                            self.wgt_met.tab_trav.item(r, 1).data(0) / 2
                    )
                elif forme_arche == 2:
                    z_top = self.wgt_met.tab_trav.item(r, 3).data(0)
                sql = (
                    "SELECT MAX(z) FROM {0}.profil_struct "
                    "WHERE id_config = {1} AND x >= {2} AND x <= {3}".format(
                        self.mdb.SCHEMA, id_struct, x_tmp, larg + x_tmp
                    )
                )
                rows = self.mdb.run_query(sql, fetch=True)
                profil_z_max = rows[0][0]
                if profil_z_max >= z_top:
                    arche_err.append(r + 1)
            x_tmp += larg

        if len(arche_err) > 0:
            txt_arche = ""
            for arche in arche_err:
                txt_arche += "{}, ".format(arche)
            return False, "Arche(s) {} : Z haut <= Cote max du profil".format(txt_arche[:-2])
        else:
            return True, None

    def verif_radier_tab(self):
        rad_err = []
        cote_tablier = ctrl_get_value(self.wgt_met.dico_ctrl["ZTOPTAB"][0])
        for r in range(self.wgt_met.tab_trav.rowCount()):
            z_top = self.wgt_met.tab_trav.item(r, 0).data(0) + self.wgt_met.tab_trav.item(
                r, 1
            ).data(0)
            if z_top >= cote_tablier:
                rad_err.append(r + 1)

        if len(rad_err) > 0:
            txt_rad = ""
            for rad in rad_err:
                txt_rad += "{}, ".format(rad)
            return False, "Dalot(s) {} : Z haut >= Cote du haut du tablier".format(txt_rad[:-2])
        else:
            return True, None

    def verif_buse_tab(self):
        buse_err = []
        cote_tablier = ctrl_get_value(self.wgt_met.dico_ctrl["ZTOPTAB"][0])
        for r in range(self.wgt_met.tab_trav.rowCount()):
            z_top = self.wgt_met.tab_trav.item(r, 1).data(0) + self.wgt_met.tab_trav.item(
                r, 2
            ).data(0)
            if z_top >= cote_tablier:
                buse_err.append(r + 1)

        if len(buse_err) > 0:
            txt_buse = ""
            for buse in buse_err:
                txt_buse += "{}, ".format(buse)
            return False, "Buse(s) {} : Z haut >= Cote du haut du tablier".format(txt_buse[:-2])
        else:
            return True, None

    def verif_buse_intersect(self):
        buse_err = []
        for c1 in range(self.wgt_met.tab_trav.rowCount()):
            x_c = self.wgt_met.tab_trav.item(c1, 0).data(0)
            ray = self.wgt_met.tab_trav.item(c1, 2).data(0) / 2
            z_c = self.wgt_met.tab_trav.item(c1, 1).data(0) + ray
            circ1 = Point([x_c, z_c]).buffer(ray)
            for c2 in range(c1 + 1, self.wgt_met.tab_trav.rowCount()):
                x_c = self.wgt_met.tab_trav.item(c2, 0).data(0)
                ray = self.wgt_met.tab_trav.item(c2, 2).data(0) / 2
                z_c = self.wgt_met.tab_trav.item(c2, 1).data(0) + ray
                circ2 = Point([x_c, z_c]).buffer(ray)
                if circ1.intersects(circ2):
                    buse_err.append((c1, c2))

        if len(buse_err) > 0:
            txt_buse = ""
            for buse in buse_err:
                txt_buse += "{}, ".format(buse)
            return False, "Intersection(s) detectee(s) : {}".format(txt_buse[:-2])
        else:
            return True, None

    # floodgate
    def init_gui_fg(self):
        """initialisation GUI for floodGate"""

        sql = "SELECT active FROM {0}.struct_fg " "WHERE id_config = {1}".format(
            self.mdb.SCHEMA, self.id_struct
        )

        rows = self.mdb.run_query(sql, fetch=True)

        if len(rows) > 0:
            self.fg_active.setChecked(bool(rows[0][0]))
        self.display_fg()

        self.act_active_fg()
        self.fg_active.stateChanged.connect(self.act_active_fg)
        self.b_fg.clicked.connect(self.get_param_fg)

    def act_active_fg(self):
        act_val = bool(self.fg_active.isChecked())
        if act_val:
            self.b_fg.setEnabled(True)
            if self.check_exit_fg():
                sql = "UPDATE {0}.struct_fg SET active = {2}  WHERE id_config = {1} ".format(
                    self.mdb.SCHEMA, self.id_struct, act_val
                )
                self.mdb.execute(sql)
            else:
                sql = "INSERT INTO {0}.struct_fg (id_config, id_scen, active, type_fg) VALUES ({1}, {2}, {3}, '{4}')".format(
                    self.mdb.SCHEMA, self.id_struct, 0, act_val, "D"
                )
                self.mdb.execute(sql)
        else:
            self.b_fg.setEnabled(False)
            if self.check_exit_fg():
                sql = "UPDATE {0}.struct_fg SET active = {2}  WHERE id_config = {1} ".format(
                    self.mdb.SCHEMA, self.id_struct, act_val
                )
                self.mdb.execute(sql)

    def display_fg(self):
        meth = self.cb_met_calc.itemData(self.cb_met_calc.currentIndex())
        if meth == 4 or meth == 0 or not self.mgis.cond_api:
            self.fg_active.setChecked(False)
            self.fg_active.hide()
            self.b_fg.hide()
        else:
            self.fg_active.show()
            self.b_fg.show()

    def check_exit_fg(self):
        """check if id_config is struct_fg table"""
        if self.id_struct:
            sql = "SELECT * FROM {0}.struct_fg WHERE id_config = {1} ".format(
                self.mdb.SCHEMA, self.id_struct
            )
            row = self.mdb.run_query(sql, fetch=True)
            return len(row) > 0
        else:
            return False

    def get_param_fg(self):
        wfg = StructureFgDialog(self.mgis, self.id_struct)
        wfg.exec_()
        del wfg

    def sav_meth(self, id_config, idmethod, ui):
        """
        Compute law
        :param id_config: index of hydraulic structure
        :param idmethod: index of method
        :param ui: gui object
        :return:
        """
        self.meth = ClassLaws(self.mgis)
        if idmethod == 0 or idmethod == 4:  # meth
            list_final = self.meth.bradley(id_config, self.tbst.dico_meth_calc[idmethod], ui)
        elif idmethod == 1:  # borda
            list_final = self.meth.borda(id_config, self.tbst.dico_meth_calc[idmethod], ui)
        elif idmethod == 3:  # orifice
            list_final = self.meth.orifice(id_config, self.tbst.dico_meth_calc[idmethod], ui)
        else:
            pass
        self.save_list_final(list_final, id_config, self.tbst.dico_meth_calc[idmethod])
        if ui is not None:
            ui.progress_bar(100)
        self.mgis.add_info(self.meth.msg)

    def save_list_final(self, list_final, id_config, method):
        """
        Save in database the law value
        :param list_final: list of law values
        :param id_config:  index of hydraulic structure
        :param method: mehtod of compute
        :return: nothing
        """
        if not list_final:
            sql = "SELECT name FROM {0}.{1} WHERE id={2}".format(
                self.mdb.SCHEMA, "struct_config", id_config
            )

            name = self.mdb.run_query(sql, fetch=True)
            name = name[0][0]

            sql = "UPDATE {0}.{1} SET {2}  WHERE id={3};".format(
                self.mdb.SCHEMA, "struct_config", "active=False", id_config
            )
            self.mdb.run_query(sql)

            self.mgis.add_info(
                "No values for the law because the coefficients leave application domain of the method.\n"
                "The <<{}>> hydraulic structur is deactivated".format(name)
            )
        else:
            self.save_law_st(method, id_config, list_final)

    def save_law_st(self, method, id_config, list_val):
        """
        Stock law in database
        :param method: mehtod of compute
        :param id_config: index of hydraulic structure
        :param list_val: value list
        :return:
        """
        """ stock law in database"""
        self.mdb.delete("struct_laws", where="id_config = '{}'".format(id_config))
        liste_col = self.mdb.list_columns("struct_laws")
        list_insert = []
        list_val = np.array(list_val)
        for j in self.tbst.dico_law_struct[method].keys():
            for i, val in enumerate(list_val[:, j]):
                list_insert.append([id_config, j, i, val])
        var = ",".join(liste_col)

        sql = ""
        for a in list_insert:
            valeurs = str(tuple(a))
            sql += "INSERT INTO {0}.{1}({2}) VALUES {3};".format(
                self.mdb.SCHEMA, "struct_laws", var, valeurs
            )
        self.mdb.run_query(sql)
