"""
/***************************************************************************
 qgSurf - plugin for Quantum GIS

 Processing of geological planes and surfaces

                              -------------------
        begin                : 2011-12-21
        copyright            : (C) 2011-2023 by Mauro Alberti
        email                : alberti.m65@gmail.com

 ***************************************************************************/

# licensed under the terms of GNU GPL 3

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""

# -*- coding: utf-8 -*-

from builtins import object

import os

from qgis.core import QgsProject
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *

from . import resources

from gst.qt.tools import *
from gst.yaml.io import *
from gst.qgis.messages import *

from .configurations.general_params import *

from .tools.BestFitPlaneTool import BestFitPlaneWidget
from .tools.DEMPlaneIntersectionTool import DemPlaneIntersectionWidget
from .tools.PlaneDistancesTool import PlaneDistancesWidget
from .tools.StereoplotTool import StereoplotWidget
from .tools.GeoprofilerTool import GeoprofilerWidget
from .tools.AboutDialog import AboutDialog


class QgSurfGui(object):

    def __init__(self, interface):

        self.pluginName = "qgSurf"
        self.plugin_folder = os.path.dirname(__file__)
        self.config_fldrpth = os.path.join(
            self.plugin_folder,
            config_folder_name)

        plugin_config_file = os.path.join(
            self.config_fldrpth,
            plugin_params_flnm)

        dPluginParams = read_yaml(plugin_config_file)

        self.version = dPluginParams["version"]
        self.tools = dPluginParams["tools"]

        self.bestfitplane_toolpars = self.tools["bestfitplane_tool_params"]
        self.demplaneinters_toolpars = self.tools["demplaneinters_tool_params"]
        self.planedistances_toolpars = self.tools["planedistances_tool_params"]
        self.geoprofiler_toolpars = self.tools["geoprofiler_tool_params"]
        self.stereonet_toolpars = self.tools["stereonet_tool_params"]
        self.about_toolpars = self.tools["about_dlg_params"]

        db_config_file = os.path.join(
            self.config_fldrpth,
            db_params_flnm)
        db_params = read_yaml(db_config_file)
        self.sqlite_db_params = db_params["sqlite_db"]

        self.best_fit_plane_module_open = False
        self.dem_plane_intersection_module_open = False
        self.plane_distances_module_open = False
        self.geoprofiler_module_open = False
        self.stereoplot_module_open = False

        self.interface = interface
        self.main_window = self.interface.mainWindow()
        self.canvas = self.interface.mapCanvas()

    def initGui(self):

        self.bestfitplane_geoproc = make_qaction(
            tool_params=self.bestfitplane_toolpars,
            plugin_name=plugin_name,
            icon_folder=icon_folder,
            parent=self.main_window)
        self.bestfitplane_geoproc.triggered.connect(self.RunBestFitPlaneGeoproc)
        self.interface.addPluginToMenu(
            plugin_name,
            self.bestfitplane_geoproc)

        self.demplaneinters_geoproc = make_qaction(
            tool_params=self.demplaneinters_toolpars,
            plugin_name=plugin_name,
            icon_folder=icon_folder,
            parent=self.main_window)
        self.demplaneinters_geoproc.triggered.connect(self.RunDemPlaneIntersectionGeoproc)
        self.interface.addPluginToMenu(
            plugin_name,
            self.demplaneinters_geoproc)

        self.planedistances_geoproc = make_qaction(
            tool_params=self.planedistances_toolpars,
            plugin_name=plugin_name,
            icon_folder=icon_folder,
            parent=self.main_window)
        self.planedistances_geoproc.triggered.connect(self.RunPlaneDistancesGeoproc)
        self.interface.addPluginToMenu(
            plugin_name,
            self.planedistances_geoproc)

        self.geoprofiler_geoproc = make_qaction(
            tool_params=self.geoprofiler_toolpars,
            plugin_name=plugin_name,
            icon_folder=icon_folder,
            parent=self.main_window)
        self.geoprofiler_geoproc.triggered.connect(self.RunGeoprofilerGeoproc)
        self.interface.addPluginToMenu(
            plugin_name,
            self.geoprofiler_geoproc)

        self.stereonet_geoproc = make_qaction(
            tool_params=self.stereonet_toolpars,
            plugin_name=plugin_name,
            icon_folder=icon_folder,
            parent=self.main_window)
        self.stereonet_geoproc.triggered.connect(self.RunStereonetGeoproc)
        self.interface.addPluginToMenu(
            plugin_name,
            self.stereonet_geoproc)

        self.qgsurf_about = make_qaction(
            tool_params=self.about_toolpars,
            plugin_name=plugin_name,
            icon_folder=icon_folder,
            parent=self.main_window)
        self.qgsurf_about.triggered.connect(self.RunQgsurfAbout)
        self.interface.addPluginToMenu(
            plugin_name,
            self.qgsurf_about)

        self.geoprocessings = [
            self.bestfitplane_geoproc,
            self.demplaneinters_geoproc,
            self.planedistances_geoproc,
            self.geoprofiler_geoproc,
            self.stereonet_geoproc,
            self.qgsurf_about]

    def RunBestFitPlaneGeoproc(self):

        if self.best_fit_plane_module_open:
            warn_qgis(
                self.pluginName,
                "Best fit plane widget already open"
            )
            return

        if QgsProject.instance().crs().isGeographic():
            warn_qgis(
                self.pluginName,
                "Before using the BestFitPlane module please set the project crs to a non-geographical one"
            )
            return

        BestFitPlaneDockWidget = QDockWidget(
            "{} - {}".format(plugin_name, self.bestfitplane_toolpars["module_name"]),
            self.interface.mainWindow())
        BestFitPlaneDockWidget.setAttribute(Qt.WA_DeleteOnClose)
        BestFitPlaneDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.BestFitPlaneQwidget = BestFitPlaneWidget(
            os.path.dirname(__file__),
            module_name=self.bestfitplane_toolpars["module_name"],
            canvas=self.canvas,
            plugin_qaction=self.bestfitplane_geoproc,
            db_tables_params=self.sqlite_db_params)
        BestFitPlaneDockWidget.setWidget(self.BestFitPlaneQwidget)
        BestFitPlaneDockWidget.destroyed.connect(self.BestFitPlaneCloseEvent)
        self.interface.addDockWidget(Qt.RightDockWidgetArea, BestFitPlaneDockWidget)

        self.best_fit_plane_module_open = True

    def RunDemPlaneIntersectionGeoproc(self):

        if self.dem_plane_intersection_module_open:
            warn_qgis(
                self.pluginName,
                "DEM-plane intersections widget already open"
            )
            return

        DemPlaneIntersectionDockWidget = QDockWidget(
            "{} - {}".format(plugin_name, self.demplaneinters_toolpars["module_name"]),
            self.interface.mainWindow())
        DemPlaneIntersectionDockWidget.setAttribute(Qt.WA_DeleteOnClose)
        DemPlaneIntersectionDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.DemPlaneIntersectionQwidget = DemPlaneIntersectionWidget(
            plugin_folder=os.path.dirname(__file__),
            module_name=self.demplaneinters_toolpars["module_name"],
            canvas=self.canvas,
            plugin_qaction=self.demplaneinters_geoproc)
        DemPlaneIntersectionDockWidget.setWidget(self.DemPlaneIntersectionQwidget)
        DemPlaneIntersectionDockWidget.destroyed.connect(self.DemPlaneIntersectionCloseEvent)
        self.interface.addDockWidget(Qt.RightDockWidgetArea, DemPlaneIntersectionDockWidget)

        self.dem_plane_intersection_module_open = True

    def RunPlaneDistancesGeoproc(self):

        if self.plane_distances_module_open:
            warn_qgis(
                self.pluginName,
                "Plane distances widget already open"
            )
            return

        PlaneDistancesDockWidget = QDockWidget(
            f"{plugin_name} - {self.planedistances_toolpars['module_name']}",
            self.interface.mainWindow()
        )
        PlaneDistancesDockWidget.setAttribute(Qt.WA_DeleteOnClose)
        PlaneDistancesDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.PlaneDistancesQwidget = PlaneDistancesWidget(
            plugin_folder=os.path.dirname(__file__),
            module_name=self.planedistances_toolpars["module_name"],
            canvas=self.canvas,
            plugin_qaction=self.planedistances_geoproc)
        PlaneDistancesDockWidget.setWidget(self.PlaneDistancesQwidget)
        PlaneDistancesDockWidget.destroyed.connect(self.PlaneDistancesCloseEvent)
        self.interface.addDockWidget(Qt.RightDockWidgetArea, PlaneDistancesDockWidget)

        self.plane_distances_module_open = True

    def RunGeoprofilerGeoproc(self):

        self.wdgtGeoprofiler = GeoprofilerWidget(
            os.path.dirname(__file__),
            plugin_name,
            self.canvas
        )

        #self.wdgtGeoprofiler.destroyed.connect(self.GeoprofilerCloseEvent)

        # show dialog
        self.wdgtGeoprofiler.show()

        self.geoprofiler_module_open = True

    def RunStereonetGeoproc(self):

        if self.stereoplot_module_open:
            warn_qgis(
                self.pluginName,
                "Geologic stereonets widget already open"
            )
            return

        dwgtStereoplotDockWidget = QDockWidget(
            "{} - {}".format(plugin_name,
            self.stereonet_toolpars["module_name"]),
            self.interface.mainWindow()
        )

        dwgtStereoplotDockWidget.setAttribute(Qt.WA_DeleteOnClose)
        dwgtStereoplotDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.wdgtStereoplot = StereoplotWidget(
            module_name=self.stereonet_toolpars["module_name"],
            canvas=self.canvas,
            settings_name=settings_name,
            plugin_folder=self.plugin_folder)

        dwgtStereoplotDockWidget.setWidget(self.wdgtStereoplot)
        dwgtStereoplotDockWidget.destroyed.connect(self.StereoplotCloseEvent)
        self.interface.addDockWidget(Qt.RightDockWidgetArea, dwgtStereoplotDockWidget)

        self.stereoplot_module_open = True

    def RunQgsurfAbout(self):

        qgsurf_about_dlg = AboutDialog(
            version=self.version)

        qgsurf_about_dlg.show()
        qgsurf_about_dlg.exec_()

    def BestFitPlaneCloseEvent(self, event):

        for mrk in self.BestFitPlaneQwidget.best_fit_plane_point_markers:
            self.BestFitPlaneQwidget.canvas.scene().removeItem(mrk)

        try:
            QgsProject.instance().layerWasAdded.disconnect(self.BestFitPlaneQwidget.refresh_raster_layer_list)
        except:
            pass

        try:
            QgsProject.instance().layerRemoved.disconnect(self.BestFitPlaneQwidget.refresh_raster_layer_list)
        except:
            pass

        try:
            self.BestFitPlaneQwidget.emit_point_from_canvas.canvasClicked.disconnect(
                self.BestFitPlaneQwidget.add_input_qgis_xy_point_to_listing)
        except:
            pass

        try:
            QgsProject.instance().layerWasAdded.disconnect(self.BestFitPlaneQwidget.refresh_layer_xy_list_in_combobox)
        except:
            pass

        try:
            QgsProject.instance().layerRemoved.disconnect(self.BestFitPlaneQwidget.refresh_layer_xy_list_in_combobox)
        except:
            pass

        try:
            self.BestFitPlaneQwidget.emit_point_from_canvas.leftClicked.disconnect(
                self.BestFitPlaneQwidget.add_input_qgis_xy_point_to_listing)
        except:
            pass

        self.best_fit_plane_module_open = False

    def DemPlaneIntersectionCloseEvent(self, event):

        for mrk in self.DemPlaneIntersectionQwidget.intersections_markers_list:
            self.DemPlaneIntersectionQwidget.canvas.scene().removeItem(mrk)

        for mrk in self.DemPlaneIntersectionQwidget.source_point_marker_list:
            self.DemPlaneIntersectionQwidget.canvas.scene().removeItem(mrk)

        try:
            self.DemPlaneIntersectionQwidget.map_tool.canvasClicked.disconnect(
                self.DemPlaneIntersectionQwidget.update_source_point_location)
        except:
            pass

        self.dem_plane_intersection_module_open = False

    def PlaneDistancesCloseEvent(self, event):

        for mrk in self.PlaneDistancesQwidget.source_point_marker_list:
            self.PlaneDistancesQwidget.canvas.scene().removeItem(mrk)

        try:
            self.PlaneDistancesQwidget.map_tool.canvasClicked.disconnect(
                self.PlaneDistancesQwidget.update_source_point_location)
        except:
            pass

        self.plane_distances_module_open = False

    def GeoprofilerCloseEvent(self):

        self.geoprofiler_module_open = False

    def StereoplotCloseEvent(self):

        self.stereoplot_module_open = False

    def unload(self):

        for geoprocessing in self.geoprocessings:

            self.interface.removePluginMenu(
                plugin_name,
                geoprocessing)
