# -*- coding: utf-8 -*-
"""
/***************************************************************************
 PreCourlisPlugin
                                 A QGIS plugin
 Creation de profils pour Courlis
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2020-03-13
        git sha              : $Format:%H$
        copyright            : (C) 2020 by EDF Hydro, DeltaCAD, Camptocamp
        email                : matthieu.secher@edf.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.path
from functools import partial
from pathlib import Path
import PreCourlis

from qgis.core import QgsApplication, QgsProject, QgsVectorLayer, Qgis
from qgis.PyQt.QtCore import (
    Qt,
    QLocale,
    QSettings,
    QTranslator,
    qVersion,
    QCoreApplication,
)
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction, QMenu, QToolButton
from qgis.utils import iface
from processing import execAlgorithmDialog

from PreCourlis.core.settings import settings
from PreCourlis.processing.precourlis_provider import PreCourlisProvider
from PreCourlis.widgets.about_dialog import AboutDialog
from PreCourlis.widgets.profile_dialog import ProfileDialog
from PreCourlis.widgets.settings_dialog import SettingsDialog
from PreCourlis.widgets.interpolation_areas_config_dialog import (
    InterpolationAreasConfigDialog,
)

# Initialize Qt resources from file resources.py
from PreCourlis.ui import resources_rc  # noqa


class PreCourlisPlugin:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value("locale/userLocale", QLocale().name())[0:2]
        locale_path = os.path.join(self.plugin_dir, "i18n", "{}.qm".format(locale))
        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > "4.3.3":
                QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.menu = None
        self.toolButton = None
        self.toolBtnAction = None

        # Dialogs
        self.profile_dialogs = []
        self.interpolation_areas_config_dialog = None

        self.provider = None

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate("PreCourlisPlugin", message)

    def initProcessing(self):
        """Init Processing provider for QGIS >= 3.8."""
        self.provider = PreCourlisProvider()
        QgsApplication.processingRegistry().addProvider(self.provider)

    def applyProfileStyleToLayer(self, checked: bool):
        layer: QgsVectorLayer = iface.activeLayer()
        style_path = (
            Path(PreCourlis.__file__).parent.resolve()
            / "resources"
            / "styles"
            / "profile_line.qml"
        )
        layer.loadNamedStyle(style_path)

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        self.initProcessing()
        precourlis_icon = QIcon(
            str(Path(PreCourlis.__file__).parent.resolve() / "resources" / "icon.png")
        )

        self.layer_style_action = QAction(iface.mainWindow())
        self.layer_style_action.setText("Apply PreCourlis symbology")
        self.layer_style_action.setIcon(precourlis_icon)
        self.layer_style_action.triggered.connect(self.applyProfileStyleToLayer)
        try:
            # QGIS >= 3.30
            iface.addCustomActionForLayerType(
                action=self.layer_style_action,
                menu="",
                type=Qgis.LayerType.Vector,
                allLayers=True,
            )
        except AttributeError:
            # QGIS <= 3.28
            from qgis.core import QgsMapLayerType

            iface.addCustomActionForLayerType(
                action=self.layer_style_action,
                menu="",
                type=QgsMapLayerType.VectorLayer,
                allLayers=True,
            )

        import_icon = QIcon(
            str(
                Path(PreCourlis.__file__).parent.resolve()
                / "resources"
                / "images"
                / "mIconModelInput.svg"
            )
        )
        reverse_icon = QIcon(
            str(
                Path(PreCourlis.__file__).parent.resolve()
                / "resources"
                / "images"
                / "mActionReverseLine.svg"
            )
        )
        edit_profile_icon = QIcon(
            str(
                Path(PreCourlis.__file__).parent.resolve()
                / "resources"
                / "images"
                / "mLayoutItemElevationProfile.svg"
            )
        )
        process_icon = QIcon(
            str(
                Path(PreCourlis.__file__).parent.resolve()
                / "resources"
                / "images"
                / "processingAlgorithm.svg"
            )
        )
        export_icon = QIcon(
            str(
                Path(PreCourlis.__file__).parent.resolve()
                / "resources"
                / "images"
                / "mIconModelOutput.svg"
            )
        )
        settings_icon = QIcon(
            str(
                Path(PreCourlis.__file__).parent.resolve()
                / "resources"
                / "images"
                / "settings.svg"
            )
        )

        self.menu = QMenu("PreCourlis", self.iface.mainWindow())

        self.add_action(
            self.tr("Georeference and import a .geo file"),
            self.georeferencing,
            icon=import_icon,
        )
        self.add_action(
            self.tr("Import a .georef / .georefC file"),
            self.import_georef,
            icon=import_icon,
        )
        self.add_action(
            self.tr("Reverse the direction of the hydraulic axis"),
            self.reverse_axe,
            icon=reverse_icon,
        )
        self.add_action(
            self.tr("Convert tracks to profiles"),
            self.import_tracks,
            icon=import_icon,
        )
        self.add_action(
            self.tr("Convert points to profiles"),
            self.import_points,
            icon=import_icon,
        )
        self.add_action(
            self.tr("Repair profiles layer"),
            self.repair_profiles,
            icon=import_icon,
        )

        self.menu.addSeparator()

        self.add_action(
            self.tr("View profiles"),
            self.open_editor,
            icon=edit_profile_icon,
        )
        main_action = QAction()
        main_action.setIcon(precourlis_icon)
        main_action.triggered.connect(self.open_editor)

        self.add_action(
            self.tr("Add intermediate profiles"),
            self.add_intermediate_profiles,
            icon=process_icon,
        )

        self.menu.addSeparator()

        self.add_action(
            self.tr("Join points to profiles"),
            self.join_points_to_profiles,
            icon=process_icon,
            tooltip=self.tr(
                "This algorithm fill raw points with corresponding profile identifier"
                " using a buffer around profiles."
            ),
        )

        self.add_action(
            self.tr("Import sedimental interface from points"),
            self.import_layer_from_points,
            icon=process_icon,
            tooltip=self.tr(
                "This algorithm fill a sedimental interface altitude from points."
            ),
        )

        self.add_action(
            self.tr("Define topography / bathymetry from a polygon"),
            self.define_topo_bath,
            icon=process_icon,
            tooltip=self.tr(
                "This algorithm define topography / bathymetry from a polygon."
            ),
        )

        self.menu.addSeparator()

        self.add_action(
            self.tr("Interpolate profiles"),
            self.interpolate_profiles,
            icon=process_icon,
        )
        self.add_action(
            self.tr("Configure interpolation areas"),
            self.configure_interpolation_areas,
            icon=process_icon,
        )
        self.add_action(
            self.tr("Interpolate profiles with areas"),
            self.interpolate_profiles_per_areas,
            icon=process_icon,
        )

        self.add_action(
            self.tr("Interpolate without lateral resampling"),
            self.interpolate_profiles_without_lateral_resampling,
            icon=process_icon,
        )

        self.menu.addSeparator()

        self.add_action(
            self.tr("Export a Courlis geometry file"),
            self.export_courlis,
            icon=export_icon,
        )
        self.add_action(
            self.tr("Export a Mascaret geometry file"),
            self.export_mascaret,
            icon=export_icon,
        )
        self.add_action(
            self.tr("Export a Mobili geometry file"),
            self.export_mobili,
            icon=export_icon,
        )
        self.add_action(
            self.tr("Export a VisuProfil file"),
            self.export_visu_profil,
            icon=export_icon,
        )

        self.menu.addSeparator()

        self.add_action(self.tr("Settings"), self.open_settings, icon=settings_icon)
        self.add_action(self.tr("About"), self.open_about, icon=precourlis_icon)

        try:
            import debugpy  # noqa

            self.menu.addSeparator()
            debugpy_icon = QgsApplication.getThemeIcon("/console/mIconRunConsole.svg")
            self.debug_action = self.add_action(
                self.tr("Start debugpy and wait for client"),
                self.start_debugpy,
                icon=debugpy_icon,
            )
        except ModuleNotFoundError:
            pass

        self.toolButton = QToolButton(self.iface.mainWindow())
        self.toolButton.setIcon(precourlis_icon)
        self.toolButton.setMenu(self.menu)
        self.toolButton.setPopupMode(QToolButton.ToolButtonPopupMode.MenuButtonPopup)
        self.toolButton.setDefaultAction(main_action)
        self.toolBtnAction = self.iface.addToolBarWidget(self.toolButton)
        # self.toolButton.triggered.connect(self.open_editor)

        self.iface.pluginMenu().addMenu(self.menu)

    def start_debugpy(self):
        import debugpy

        debugpy.listen(("127.0.0.1", 5679))

    def add_action(self, text, slot, icon=None, tooltip=None):
        action = QAction(self.menu)
        action.setText(text)
        if icon is not None:
            action.setIcon(icon)
        if tooltip:
            action.setToolTip(tooltip)
        action.triggered.connect(slot)
        self.menu.addAction(action)
        return action

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        QgsApplication.processingRegistry().removeProvider(self.provider)

        if hasattr(self, "layer_style_action"):
            iface.removeCustomActionForLayerType(self.layer_style_action)

        self.iface.removeToolBarIcon(self.toolBtnAction)
        self.toolButton.deleteLater()
        self.menu.deleteLater()

        for dialog in self.profile_dialogs:
            dialog.deleteLater()

        if self.interpolation_areas_config_dialog is not None:
            self.interpolation_areas_config_dialog.deleteLater()

    def georeferencing(self):
        execAlgorithmDialog("precourlis:georeferencing", {})

    def import_georef(self):
        execAlgorithmDialog(
            "precourlis:import_georef", {"CRS": QgsProject.instance().crs().authid()}
        )

    def reverse_axe(self):
        execAlgorithmDialog("native:reverselinedirection", {})

    def import_tracks(self):
        params = {"DEFAULT_ELEVATION": settings.default_elevation}
        execAlgorithmDialog("precourlis:import_tracks", params)

    def import_points(self):
        params = {"DEFAULT_ELEVATION": settings.default_elevation}
        execAlgorithmDialog("precourlis:import_points", params)

    def repair_profiles(self):
        execAlgorithmDialog("precourlis:repair_profiles", {})

    def open_editor(self):
        dialog = ProfileDialog(self.iface.mainWindow())
        dialog.setAttribute(Qt.WA_DeleteOnClose)
        dialog.destroyed.connect(partial(self.profile_dialog_destroyed, dialog))
        dialog.show()
        self.profile_dialogs.append(dialog)

    def add_intermediate_profiles(self):
        execAlgorithmDialog("precourlis:add_intermediate_profiles", {})

    def profile_dialog_destroyed(self, dialog):
        dialog.graphWidget.close_figure()
        self.profile_dialogs.remove(dialog)

    def join_points_to_profiles(self):
        execAlgorithmDialog("precourlis:join_points_to_profiles", {})

    def import_layer_from_points(self):
        execAlgorithmDialog("precourlis:import_layer_from_points", {})

    def define_topo_bath(self):
        execAlgorithmDialog("precourlis:define_topo_bath", {})

    def interpolate_profiles(self):
        execAlgorithmDialog("precourlis:interpolate_lines", {})

    def configure_interpolation_areas(self):
        if self.interpolation_areas_config_dialog is None:
            self.interpolation_areas_config_dialog = InterpolationAreasConfigDialog(
                self.iface.mainWindow()
            )
        self.interpolation_areas_config_dialog.show()
        self.interpolation_areas_config_dialog.raise_()

    def interpolate_profiles_per_areas(self):
        execAlgorithmDialog("precourlis:interpolate_profiles_per_areas")

    def interpolate_profiles_without_lateral_resampling(self):
        execAlgorithmDialog("precourlis:interpolate_without_lateral_resampling")

    def export_courlis(self):
        execAlgorithmDialog("precourlis:export_courlis")

    def export_mascaret(self):
        execAlgorithmDialog("precourlis:export_mascaret")

    def open_settings(self):
        settings_dialog = SettingsDialog(self.iface.mainWindow())
        settings_dialog.exec_()
        settings_dialog.deleteLater()

    def open_about(self):
        dlg = AboutDialog(self.iface.mainWindow())
        dlg.exec_()
        dlg.deleteLater()

    def export_mobili(self):
        execAlgorithmDialog("precourlis:export_mobili")

    def export_visu_profil(self):
        execAlgorithmDialog("precourlis:export_visu_profil")
