######################################################################
#             / ____|  ____|  __ \| |  | |  ____|  ____|             #
#            | |    | |__  | |__) | |__| | |__  | |__                #
#            | |    |  __| |  ___/|  __  |  __| |  __|               #
#            | |____| |____| |    | |  | | |____| |____              #
#             \_____|______|_|    |_|  |_|______|______|             #
######################################################################
#
# CEPHEE
# Copyright (C) 2024 Toulouse INP
#
# 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details :
# <http://www.gnu.org/licenses/>.
#
######################################################################

from qgis.PyQt.QtWidgets import QDockWidget
from qgis.PyQt.QtCore import pyqtSignal
from qgis.core import   (QgsMessageLog, Qgis, QgsTask, QgsApplication, QgsVectorLayer, QgsProject,
                         QgsCoordinateReferenceSystem, QgsMapLayerProxyModel)
from .ui.Ui_CrossSectionWidget import Ui_CrossSectionWidget
from ..core.CrossSection import *


class CrossSectionWidget(QDockWidget, Ui_CrossSectionWidget):

    closingWidget = pyqtSignal(name="closingWidget")

    def __init__(self, iface, BV, param, parent = None):
        super(CrossSectionWidget, self).__init__(parent)
        self.setupUi(self)
        self.iface = iface
        self.BV = BV
        self.param = param
        self.task = None
        self.comboBox_layerXS.setFilters(QgsMapLayerProxyModel.VectorLayer)
        self.comboBox_layerXS.setAllowEmptyLayer(True, "no layer")
        self.comboBox_layerXS.setCurrentIndex(0)
        self.comboBox_layerBank_1.setAllowEmptyLayer(True, "no layer")
        self.comboBox_layerBank_1.setCurrentIndex(0)
        self.comboBox_layerBank_2.setAllowEmptyLayer(True, "no layer")
        self.comboBox_layerBank_2.setCurrentIndex(0)
        self.checkBox_widthFromBanks_1.stateChanged.connect(self.updatePanel)
        self.checkBox_widthFromBanks_2.stateChanged.connect(self.updatePanel)
        self.checkBox_resampleLines.stateChanged.connect(self.updatePanel)
        self.checkBox_interpolateXS.stateChanged.connect(self.updatePanel)
        self.checkBox_optimizeXS.stateChanged.connect(self.updatePanel)
        self.pushButton_generate.clicked.connect(self.generate_XS)
        self.pushButton_import.clicked.connect(self.import_XS)
        self.pushButton_projection.clicked.connect(self.project_XS)
        self.updatePanel()

    def closeEvent(self, event):
        self.closingWidget.emit()
        event.accept()

    def updatePanel(self):
        if self.checkBox_resampleLines.isChecked():
            self.lineEdit_number_of_points_resample.setEnabled(True)
        else:
            self.lineEdit_number_of_points_resample.setDisabled(True)
        if self.checkBox_interpolateXS.isChecked():
            self.lineEdit_XSinterstep.setEnabled(True)
            self.comboBox_interpolateXS.setEnabled(True)
        else:
            self.lineEdit_XSinterstep.setDisabled(True)
            self.comboBox_interpolateXS.setDisabled(True)
        if self.checkBox_optimizeXS.isChecked():
            self.comboBox_optimizeXS.setEnabled(True)
        else:
            self.comboBox_optimizeXS.setDisabled(True)

    def ui_to_param(self):
        if self.tabWidget.isTabVisible(0):
            # XS generation
            self.param['XS']['creation_step'] = float(self.lineEdit_creation_step.text())
            self.param['XS']['width'] = float(self.lineEdit_width.text())
            self.param['XS']['number_of_points'] = int(self.lineEdit_number_of_points.text())
            self.param['XS']['width_from_banks'] = self.checkBox_widthFromBanks_1.isChecked()
            if self.comboBox_layerBank_1.currentText() != "no layer":
                self.param['I']['riverbanks_filepath'] = self.comboBox_layerBank_1.currentLayer().dataProvider().dataSourceUri()

        elif self.tabWidget.isTabVisible(1):
            # XS import
            self.param['I']['XS_filepath'] = self.comboBox_layerXS.currentLayer().dataProvider().dataSourceUri()
            self.param['XS']['width_from_banks'] = self.checkBox_widthFromBanks_2.isChecked()
            if self.comboBox_layerBank_2.currentText() != "no layer":
                self.param['I']['riverbanks_filepath'] = self.comboBox_layerBank_2.currentLayer().dataProvider().dataSourceUri()

        # XS interpolation
        self.param['XS']['interpolate_XS'] = self.checkBox_interpolateXS.isChecked()
        self.param['XS']['interpolation_step'] = float(self.lineEdit_XSinterstep.text())
        self.param['XS']['interpolation_method'] = self.comboBox_interpolateXS.currentText()

        # XS optimisation
        self.param['XS']['optimize_XS'] = self.checkBox_optimizeXS.isChecked()
        self.param['XS']['optimization_method'] = self.comboBox_optimizeXS.currentText()
        self.param['XS']['distSearchMin'] = float(self.lineEdit_distSearchMin.text())

    def generate_XS(self):
        self.ui_to_param()
        self.task = GenerateXS('GenerateXS', self.BV, self.param)
        QgsApplication.taskManager().addTask(self.task)

    def import_XS(self):
        self.ui_to_param()
        self.task = ImportXS('ImportXS', self.BV, self.param)
        QgsApplication.taskManager().addTask(self.task)

    def project_XS(self):
        self.ui_to_param()
        self.task = ProjectXS('ProjectXS', self.BV, self.param)
        QgsApplication.taskManager().addTask(self.task)


class GenerateXS(QgsTask):

    def __init__(self, description, BV, param):
        super().__init__(description)
        self.BV = BV
        self.param = param

    def run(self):
        QgsMessageLog.logMessage(message="Starting Cross Section Generation", tag="CEPHEE", level=Qgis.MessageLevel.Info)
        self.setProgress(0)
        self.BV.createReach() # select river connected to outlet
        self.BV.interpolateReach(self.param['XS']['creation_step'])
        create_XS_lines(self.BV, self.param)
        XS_layer = QgsVectorLayer(self.param['I']['XS_filepath'], 'XS lines')
        XS_layer.setCrs(QgsCoordinateReferenceSystem(self.BV.crs.to_string()))
        QgsProject.instance().addMapLayer(XS_layer)
        self.setProgress(100)
        return True

    def finished(self, result):
        if result:
            QgsMessageLog.logMessage(message="Process OK", tag="CEPHEE", level=Qgis.MessageLevel.Info)
        else:
            QgsMessageLog.logMessage(message="Process Error", tag="CEPHEE", level=Qgis.MessageLevel.Critical)


class ImportXS(QgsTask):

    def __init__(self, description, BV, param):
        super().__init__(description)
        self.BV = BV
        self.param = param

    def run(self):
        QgsMessageLog.logMessage(message="Starting Cross Section Import", tag="CEPHEE", level=Qgis.MessageLevel.Info)
        self.setProgress(0)
        self.BV.createReach()
        import_XS_lines(self.BV, self.param)
        self.setProgress(100)
        return True

    def finished(self, result):
        if result:
            QgsMessageLog.logMessage(message="Process OK", tag="CEPHEE", level=Qgis.MessageLevel.Info)
        else:
            QgsMessageLog.logMessage(message="Process Error", tag="CEPHEE", level=Qgis.MessageLevel.Critical)


class ProjectXS(QgsTask):

    def __init__(self, description, BV, param):
        super().__init__(description)
        self.BV = BV
        self.param = param

    def run(self):
        self.setProgress(0)

        if self.param['XS']['optimize_XS']:
            optimize_XS_lines(self.BV, self.param,method=self.param['XS']['optimization_method'],
                              max_iter=self.param['H']['MaxIter'], verbose=self.param.verbose)
            remove_crossing_XS(self.BV)

        project_XS_lines(self.BV, self.param)
        create_all_centerlines(self.BV, self.param.work_path)

        if self.param['XS']['interpolate_XS']:
            interpolate_XS_lines(self.BV, self.param)

        save_XS_lines(self.BV, self.param['I']['XS_filepath'])
        XS_layer = QgsVectorLayer(self.param['I']['XS_filepath'], 'XS lines projected')
        XS_layer.setCrs(QgsCoordinateReferenceSystem(self.BV.crs.to_string()))
        QgsProject.instance().addMapLayer(XS_layer)
        self.setProgress(100)
        return True

    def finished(self, result):
        if result:
            QgsMessageLog.logMessage(message="Process OK", tag="CEPHEE", level=Qgis.MessageLevel.Info)
        else:
            QgsMessageLog.logMessage(message="Process Error", tag="CEPHEE", level=Qgis.MessageLevel.Critical)
