# -*- coding: utf-8 -*-
"""
/***************************************************************************
Name                 : Mascaret
Description          : Pre and Postprocessing for Mascaret for QGIS
Date                 : June,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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""
import os
from datetime import datetime

from qgis.PyQt.QtCore import Qt, qVersion
from qgis.PyQt.QtWidgets import QDialog, QLabel, QProgressBar, QTreeWidgetItem
from qgis.PyQt.uic import loadUi

from ..ui.custom_control import ClassWarningBox, _qt_is_checked

QT_VERSION = [int(v) for v in qVersion().split(".")][0]


class ClassDeletrunDialog(QDialog):
    """
    Class allow to delete run
    """

    def __init__(self, mgis, iface):
        QDialog.__init__(self)
        self.mgis = mgis
        self.mdb = self.mgis.mdb
        self.iface = iface
        self.ui = loadUi(os.path.join(self.mgis.masplugPath, "ui/ui_delete.ui"), self)
        self.box = ClassWarningBox()
        self.listeRuns = []
        self.listeScen = {}
        self.cond_com = None
        self.tree = None
        self.parent = {}
        self.child = {}

        self.init_gui()

    def init_gui(self):
        """
        initialisation GUI
        """
        if QT_VERSION > 5:
            qt_tris = Qt.ItemFlag.ItemIsAutoTristate
            qt_item_check = Qt.ItemFlag.ItemIsUserCheckable
            qt_ucheck = Qt.CheckState.Unchecked

        else:
            qt_tris = Qt.ItemIsAutoTristate
            qt_item_check = Qt.ItemIsUserCheckable
            qt_ucheck = Qt.Unchecked
        self.lst_tab = self.mdb.list_tables()
        liste_col = self.mdb.list_columns("runs")
        self.cond_com = "comments" in liste_col

        dico = self.mdb.select("runs", order="date")
        if not dico:
            self.mgis.add_info("No run in database", box=True)
            return
        if self.cond_com:
            for run, scen, date, comments in zip(
                dico["run"], dico["scenario"], dico["date"], dico["comments"]
            ):
                if run not in self.listeRuns:
                    self.listeRuns.append(run)
                    self.listeScen[run] = []
                self.listeScen[run].append((scen, date, comments))
        else:
            for run, scen, date in zip(dico["run"], dico["scenario"], dico["date"]):
                if run not in self.listeRuns:
                    self.listeRuns.append(run)
                    self.listeScen[run] = []
                self.listeScen[run].append((scen, date))

        if len(self.listeRuns) > 0:
            self.tree = self.ui.treeWidget

            self.parent = {}
            self.child = {}

            for run in self.listeRuns:
                self.parent[run] = QTreeWidgetItem(self.tree)
                self.parent[run].setText(0, run)
                item_flag = self.parent[run]
                item_flag.setFlags(item_flag.flags() | qt_tris | qt_item_check)

                lbl = QLabel("")
                self.tree.setItemWidget(self.parent[run], 2, lbl)

                self.child[run] = {}
                maxi = datetime(1900, 1, 1, 0, 0)
                if self.cond_com:
                    for scen, date, comments in self.listeScen[run]:
                        self.child[run][scen] = QTreeWidgetItem(self.parent[run])
                        item_flag = self.child[run][scen]
                        item_flag.setFlags(item_flag.flags() | qt_item_check)
                        item_flag.setCheckState(0, qt_ucheck)
                        self.child[run][scen].setText(0, scen)
                        lbl = QLabel("{:%d/%m/%Y %H:%M}".format(date))
                        self.tree.setItemWidget(self.child[run][scen], 1, lbl)

                        maxi = max(maxi, date)
                        lbl = QLabel(comments)
                        self.tree.setItemWidget(self.child[run][scen], 2, lbl)
                else:
                    for scen, date in self.listeScen[run]:
                        self.child[run][scen] = QTreeWidgetItem(self.parent[run])
                        item_flag = self.child[run][scen]
                        item_flag.setFlags(item_flag.flags() | qt_item_check)
                        item_flag.setCheckState(0, qt_ucheck)

                        self.child[run][scen].setText(0, scen)

                        lbl = QLabel("{:%d/%m/%Y %H:%M}".format(date))
                        self.tree.setItemWidget(self.child[run][scen], 1, lbl)

                        maxi = max(maxi, date)

                lbl = QLabel("{:%d/%m/%Y %H:%M}".format(maxi))
                self.tree.setItemWidget(self.parent[run], 1, lbl)
        else:
            self.ui.b_delete.setDisabled(True)

        self.ui.b_delete.clicked.connect(self.lancement)
        self.ui.b_cancel.clicked.connect(self.annule)

    def lancement(self):
        """Delete selection function"""
        selection = {}
        for run in self.listeRuns:
            if _qt_is_checked(self.parent[run], check_level="any"):
                selection[run] = []
                if self.cond_com:
                    for scen, date, comments in self.listeScen[run]:
                        if _qt_is_checked(
                            self.child[run][scen],
                            check_level="partial_or_full",
                        ):
                            selection[run].append(scen)
                else:
                    for scen, date in self.listeScen[run]:
                        if _qt_is_checked(
                            self.child[run][scen],
                            check_level="partial_or_full",
                        ):
                            selection[run].append(scen)

        self.close()

        self.iface.messageBar().clearWidgets()
        progress_message_bar = self.iface.messageBar()
        progress = QProgressBar()
        progress.setMaximum(100)
        progress_message_bar.pushWidget(progress)

        n = len(selection.keys())
        ok = self.box.yes_no_q("Do you want to delete ?")

        if ok:
            for i, (run, scenarios) in enumerate(selection.items()):
                scenarios_clean = [scen.strip("'") for scen in scenarios]
                if not scenarios_clean:
                    continue

                sql = "DELETE FROM {schema}.runs WHERE run = %s AND scenario = ANY(%s::text[])"
                self.mdb.run_query(sql, schema=True, params=(run, scenarios_clean))
                self.delete_useless_data()
                self.mgis.add_info("Deletion of scenarii is done")
                progress.setValue(round(i / n * 100))

        self.iface.messageBar().clearWidgets()

    def annule(self):
        """ "Cancel"""
        self.close()

    def delete_useless_data(self):
        # delete var transport_pur
        sql = (
            "DELETE FROM {schema}.results_var WHERE id IN ("
            "SELECT DISTINCT var FROM {schema}.results "
            "WHERE id_runs NOT IN (SELECT id FROM {schema}.runs) "
            "AND type_res = %s)"
        )
        self.mdb.run_query(sql, schema=True, params=["tracer_TRANSPORT_PUR"])

        sql = (
            "DELETE FROM {schema}.results_by_pk "
            "WHERE id_runs NOT IN (SELECT id FROM {schema}.runs)"
        )
        self.mdb.run_query(sql, schema=True)

        sql = (
            "DELETE FROM {schema}.results_sect "
            "WHERE id_runs NOT IN (SELECT id FROM {schema}.runs)"
        )
        self.mdb.run_query(sql, schema=True)

        sql = (
            "DELETE FROM {schema}.runs_graph " "WHERE id_runs NOT IN (SELECT id FROM {schema}.runs)"
        )
        self.mdb.run_query(sql, schema=True)

        sql = (
            "DELETE FROM {schema}.runs_plani " "WHERE id_runs NOT IN (SELECT id FROM {schema}.runs)"
        )
        self.mdb.run_query(sql, schema=True)

        sql = (
            "DELETE FROM {schema}.assim_res " "WHERE id_runs NOT IN (SELECT id FROM {schema}.runs)"
        )
        self.mdb.run_query(sql, schema=True)

        sql = (
            "DELETE FROM {schema}.assim_res_ks "
            "WHERE id_runs NOT IN (SELECT id FROM {schema}.runs)"
        )
        self.mdb.run_query(sql, schema=True)

        sql = (
            "DELETE FROM {schema}.assim_res_law "
            "WHERE id_runs NOT IN (SELECT id FROM {schema}.runs)"
        )
        self.mdb.run_query(sql, schema=True)

        lst_tables = [
            "results_sect",
            "runs_graph",
            "results_var",
            "runs_plani",
            "results_by_pk",
            "assim_res",
            "assim_res_ks",
            "assim_res_law",
            "runs",
        ]

        # full=True (strong gain to size data and heavy in time
        #               in function the remaining data)
        #       If you empty all the results, do a vacuum full
        # anal =  True (low gain to size data and time
        #               between full and empty)
        # empty (no gain to size data, not much time)
        if self.ch_vaccum.isChecked():
            self.mdb.vacuum(lst_tables)
