# -*- coding: utf-8 -*-
"""
/***************************************************************************
 SensorThingsAPI
                                 A QGIS plugin
 The plugin enables QGIS software (www.qgis.org) to access dynamic data from sensors,
 using SensorThingsAPI protocol (https://www.ogc.org/standards/sensorthings)
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2024-04-22
        git sha              : $Format:%H$
        copyright            : (C) 2024 by Deda Next (Sandro Moretti)
        email                : sandro.moretti@dedagroup.it
 ***************************************************************************/
"""
# import QGIS modules
from qgis.core import QgsApplication

from qgis.PyQt.QtCore import qVersion, Qt, QObject, QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction, QMenu, QDockWidget

# Initialize Qt resources from file resources.py
from .resources import *

# import plugin modules
from SensorThingsAPI import __QGIS_PLUGIN_NAME__, __PLG_DEBUG__, plgConfig
from SensorThingsAPI.log.logger import QgisLogger as logger
from SensorThingsAPI.utils.layer_utils import LayerUtils 
from SensorThingsAPI.sensor_things_inspector_layer import __SENSORTHINGS_PROVIDER_NAME__
from SensorThingsAPI.sensor_things_inspector_main_panel import SensorThingsInspectorMainPanel
from SensorThingsAPI.tools.feature_selection_tool import FeatureSelectionTool
from SensorThingsAPI.sensor_things_location_dlg import SensorThingsLocationDialog

# import system modules
import os.path


class SensorThingsInspectorPlugin(QObject):
    """QGIS Plugin Sensor Things Inspector"""

    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
        """
        
        # call parent cunstructor
        QObject.__init__(self)
        
        # Save reference to the QGIS interface
        self.iface = iface
        
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        
        # initialize locale
        self.locale = QSettings().value('locale/userLocale')[0:2]
        if self.locale:
            self.locale = self.locale[0:2]
            locale_path = os.path.join(
                self.plugin_dir,
                'i18n',
                'SensorThingsInspector_{}.qm'.format(self.locale))
    
            if os.path.exists(locale_path):
                self.translator = QTranslator()
                self.translator.load(locale_path)
                if qVersion() > '4.3.3':
                    QCoreApplication.installTranslator(self.translator)
        else:
            self.locale = ''
            
            
        # menu
        self.menu = None
        self.menu_title = u'&SensorThingsInspector'
        
        # toolbar
        self.toolbar = None
        
        # actions
        self.actions = []
        
        self.inspectoAction = None
        self.exportAction = None
            
        # Plugin widgets
        self.main_panel = None
        
        # dialogs
        self.postazionedlg = None
    

    def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_menu_obj=None,
        add_to_toolbar=True,
        add_to_toolbar_obj=None,
        status_tip=None,
        whats_this=None,
        parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool
        
        :param add_to_menu_obj: Qgis menu object instance
            where to append new sub menu. Defaults to None (plugin menu).
        :type add_to_menu_obj: QMenu
        
        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool
        
        :param add_to_toolbar_obj: Qgis toolbar object instance
            where to append action. Defaults to None (plugin toolbar).
        :type add_to_toolbar_obj: QToolBar

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)
            
        if add_to_toolbar:
            if add_to_toolbar_obj is not None:
                # Adds action to request toolbar
                add_to_toolbar_obj.addAction(action)
                
            else:
                # Adds plugin action to Plugins toolbar
                self.iface.addToolBarIcon(action)
            
        if add_to_menu:
            if add_to_menu_obj:
                # Adds action to request menu
                add_to_menu_obj.addAction(action)
            else:
                # Adds plugin icon to Plugins toolbar
                self.iface.addPluginToMenu(self.menu_title, action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        
        # create Postazione info dialog
        self.postazionedlg = SensorThingsLocationDialog(self, parent=self.iface.mainWindow())
        
        # create main dockable panel
        self.main_panel = SensorThingsInspectorMainPanel(parent= QgsApplication.instance().activeWindow())
        
        self.main_panel.layerSourceChanged.connect(self.onCurrentLayerChanged)
        
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.main_panel)
        
        self.iface.currentLayerChanged.connect(self.onCurrentLayerChanged) 
        
        # create plugin menu
        menu_bar = self.iface.mainWindow().menuBar()
        self.menu = QMenu(__QGIS_PLUGIN_NAME__, menu_bar)
        menu_bar.insertMenu(menu_bar.actions()[-1], self.menu)
        
        # create plugin toolbar
        self.toolbar = self.iface.addToolBar(__QGIS_PLUGIN_NAME__)
        self.toolbar.setToolTip(self.tr('SensorThingsInspector plugin command toolbar'))
        
        # crete plugin actions
        self.add_action(
            icon_path=':/plugins/SensorThingsAPI/icons/action-show-panel-icon.png',
            text=self.tr("Setup"),
            callback=self.onShowMainPanel,
            add_to_menu=True,
            add_to_menu_obj=self.menu,
            add_to_toolbar=True,
            add_to_toolbar_obj=self.toolbar,
            parent=self.iface.mainWindow())
        
        self.menu.addSeparator()
        self.toolbar.addSeparator()
        
        self.inspectoAction = self.add_action(
            icon_path=':/plugins/SensorThingsAPI/icons/action-identify-icon.png',
            text=self.tr("Inspect"),
            callback=self.onSelectPostazioneFeature,
            add_to_menu=True,
            add_to_menu_obj=self.menu,
            add_to_toolbar=True,
            add_to_toolbar_obj=self.toolbar,
            parent=self.iface.mainWindow())
        
        self.exportAction = self.add_action(
            icon_path=':/plugins/SensorThingsAPI/icons/action-export-icon.png',
            text=self.tr("Export"),
            callback=self.onExportLayer,
            add_to_menu=True,
            add_to_menu_obj=self.menu,
            add_to_toolbar=True,
            add_to_toolbar_obj=self.toolbar,
            parent=self.iface.mainWindow())
        
        # start
        self.onCurrentLayerChanged(self.iface.activeLayer())

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        
        # remove plugin wifgets
        self.iface.currentLayerChanged.disconnect(self.onCurrentLayerChanged)
        
        # Remove dialogs
        self.postazionedlg.close()
        self.postazionedlg.deleteLater()
        self.postazionedlg = None
        
        self.main_panel.layerSourceChanged.disconnect(self.onCurrentLayerChanged)
        self.main_panel.close()
        self.iface.removeDockWidget(self.main_panel)
        self.main_panel.deleteLater()
        self.main_panel = None
    
        # remove plugin actions
        for action in self.actions:
            self.iface.removePluginMenu(self.menu_title, action)
            self.iface.removeToolBarIcon(action)
            
        # remove plugin toolbars
        if self.toolbar is not None:
            self.toolbar.deleteLater()
            
        self.toolbar = None
        
        
        # remove plugin menu
        if self.menu is not None:
            self.menu.deleteLater()
            
        self.menu = None
        
        
    def postazioniShow(self, layer, fids):
        """Slot to show Postazioni dialog"""
        
        # check if SensorThing layer
        provider = layer.dataProvider()
        if provider.name().lower() != __SENSORTHINGS_PROVIDER_NAME__:
            logger.msgbar(
                logger.Level.Warning, 
                "{}, <b>{}</b>".format(
                    self.tr("Selected entity has an illegal data source"),
                    self.tr("use a SensorThings layer")
                ),
                title=__QGIS_PLUGIN_NAME__)
            return
        
        # check if features sellected
        fids = fids or []
        if len(fids) == 0:
            return
        fid = fids[0]
        
        # show Postazione dialog inspector
        if __PLG_DEBUG__:
            self.postazionedlg.showInspector(self.postazionedlg)
            
        # show Postazione dialog
        self.postazionedlg.show(layer, fid, fids)
  
  
    def onCurrentLayerChanged(self, layer):
        """Slot for current layer changed signal"""
        
        # setup main panel
        self.main_panel.setLayer(layer)
        
        # setup actions
        self.inspectoAction.setEnabled(self.main_panel.HasValidGeometryLayer)
        
        self.exportAction.setEnabled(self.main_panel.HasValidLayer)
        
      
    def onShowMainPanel(self, hide=False, currentTabName=None):
        """ Show/Hide pluging main dockable panel. """
        if self.main_panel.isVisible():
            return
            
        # add a temporary dock widget
        dock = QDockWidget()
        dock.setFloating(self.main_panel.isFloating())
        dock.setAllowedAreas(Qt.AllDockWidgetAreas)
        self.iface.addTabifiedDockWidget(Qt.RightDockWidgetArea, dock)
        
        # need to re add dock widget for bug in Qt
        self.main_panel.setFloating(self.main_panel.isFloating())
        self.main_panel.setAllowedAreas(Qt.AllDockWidgetAreas)
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.main_panel)
        
        # Use native addTabifiedDockWidget
        self.iface.addTabifiedDockWidget(Qt.RightDockWidgetArea, self.main_panel, [dock.accessibleName()], raiseTab=True)
        
        # remove temporary dock widget
        self.iface.removeDockWidget(dock)
        
        # show panel
        self.main_panel.show()
        self.main_panel.raise_()
        
        
    def onSelectPostazioneFeature(self, checked):
        """Callback method on selected location feature"""
        
        # create and set map tool
        canvas = self.iface.mapCanvas()
        self.featureSelectionTool = FeatureSelectionTool(canvas)
        self.featureSelectionTool.featuresIdentified.connect(self.postazioniShow)
        canvas.setMapTool(self.featureSelectionTool)
        logger.msgbar(
            logger.Level.Info, 
            self.tr("Select a location"), 
            title=__QGIS_PLUGIN_NAME__,
            clear=True)
        
        
    def onExportLayer(self, checked):
        """Callback method to export active Sensorthing Layer"""
        
        layer = self.main_panel.getLayer()
        if layer is None:
            return
        
        addToMap = plgConfig.get_value("export/add_to_map", True)
        output_formats = plgConfig.get_value("export/output_formats", [])
         
        LayerUtils.saveAsVectorFile(layer, onlySelected=False, addToMap=addToMap, output_formats= output_formats)
        
        