# -*- coding: utf-8 -*-
"""
/***************************************************************************
 ChmFromLidar
                                 A QGIS plugin
 This plugin creates the Canopy Height Model (CHM) from LIDAR data.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2019-04-29
        git sha              : $Format:%H$
        copyright            : (C) 2019 by Gter srl
        email                : assistenzagis@gter.it
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""
from PyQt5.QtCore import QSettings, QTranslator, qVersion, QCoreApplication, QDir
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox, QProgressBar, QDialog, QCheckBox
from qgis.gui import QgsMessageBar, QgsProjectionSelectionDialog
#from qgis.gui import QgsRasterLayerSaveAsDialog
from qgis.core import *
from qgis.core import QgsMapLayerProxyModel
from qgis.utils import *
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
import processing
#import sys
# Initialize Qt resources from file resources.py
from .resources import *
# Import the code for the dialog
from .chm_from_lidar_dialog import ChmFromLidarDialog#, MyDialog
from datetime import datetime
import os.path
import os
import itertools
import tempfile
import shutil
from shutil import copyfile
from osgeo import gdal
from pathlib import Path
from osgeo import osr
import time
import webbrowser
import zipfile

class ChmFromLidar ():
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        #print('sono nel costruttore')
        """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')[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)

        #self.dlg = ChmFromLidarDialog()
        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&CHM from LIDAR')

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads
        #self.first_start = None
        
        self.pluginIsActive = False
        
        
        self.selectedcrs = ''
        self.chmFinalName = ''
        #self.chmFinalName2 = ''
        self.chm_path_folder = ''
        self.input_crs = ''
        #self.dlg.checkNegValBox.setChecked(False)
        #print(self.dlg.checkNegValBox.isChecked())
        self.checkNegBox = True
        self.checkChmBox = False
        self.spinMaxBox = 0
        self.comboIndex = 0
        self.enteIndex = 0
        self.aoiIndex = -1
        self.spinResBox = 0.00
        self.tableRes = 0.00
        self.NameClip = 'clip'
        self.chm_out_tempdir_s = ''
        
        self.raster_format = []
        self.show_values = []
        self.ente_values = []
        self.lyr = ''
        self.rs_count = 0
        #self.dlg.checkNegValBox.stateChanged.connect(lambda:self.handleCheckBox(self.dlg.checkNegValBox))
        #self.dlg.checkNegValBox.toggle()
		
		#self.dlg.ctest = QCheckBox('')
		#self.dlg.ctest.toggled.connect(lambda:self.handleCheckBox(self.dlg.checkNegValBoxTest))
        
        self.enableCalc2 = {True: self.calc2, False: self.noop}
        self.enableCalc3 = {True: self.calc3, False: self.noop}
        #self.enableClip = {True: self.clip, False: self.noop}

    # 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('ChmFromLidar', message)


    def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        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_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :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:
            # Adds plugin icon to Plugins toolbar
            self.iface.addToolBarIcon(action)

        if add_to_menu:
            self.iface.addPluginToMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

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

        icon_path = ':/plugins/chm_from_lidar/icon.png'
        self.add_action(
            icon_path,
            text=self.tr(u'Compute CHM'),
            callback=self.pressIcon,
            parent=self.iface.mainWindow())

        # will be set False in run()
        self.first_start = True
        #print('sono in initgui')
        self.dlg = ChmFromLidarDialog()
        

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(
                self.tr(u'&CHM from LIDAR'),
                action)
            self.iface.removeToolBarIcon(action)
            
    def importDsmButton(self):
        self.dsm_folder = QFileDialog.getExistingDirectory()
        #print (self.dsm_folder)
        dsm_txt_folder = self.dlg.import_dsm.setText(self.dsm_folder) #scrive semplicemente la url nel form della gui
        #print (dsm_sel_folder)
        #return dsm_folder
        
    def importDtmButton(self):
        self.dtm_folder = QFileDialog.getExistingDirectory()
        #print (self.dtm_folder)
        dtm_txt_folder = self.dlg.import_dtm.setText(self.dtm_folder) #scrive semplicemente la url nel form della gui
        #print (dsm_sel_folder)
        #return dsm_folder
        
    def exportChmButton(self):
        self.chm_folder = QFileDialog.getExistingDirectory()
        self.chm_path_folder = QDir.toNativeSeparators(self.chm_folder)
        #print (self.chm_folder)
        #print (self.chm_path_folder)
        chm_txt_folder = self.dlg.export_chm.setText(self.chm_path_folder) #scrive semplicemente la url nel form della gui
        #print (dsm_sel_folder)
        #return dsm_folder
        
    def mainLog(self, selectedAoi, selectedCampaign, selectedFormat, sf):
        text = self.dlg.textLog
        if selectedAoi == None:
            txt_aoi = self.tr('no data selected')
            txt_clip = self.tr('no clip file created')
        else:
            txt_aoi = selectedAoi.name()
            txt_clip = self.NameClip
        text.append(self.tr("Input parameters: \nAOI = {},\n").format(txt_aoi) + 
        self.tr("Selected Feature Checkbos = {},").format(self.dlg.checkSelFeatbox.isChecked()))
        if self.comboIndex == 0:
            txt_camp = self.tr('no data selected')
        else:
            txt_camp = selectedCampaign
        text.append(self.tr("Campaign = {},\n").format(txt_camp) +
        self.tr("Recompute CHM = {},\n").format(self.dlg.useChmBox.isChecked()) +
        self.tr("Clip Raster Name = {},").format(txt_clip))
        if self.spinResBox == 0.00 and selectedAoi != None:
            text.append(self.tr("Clip Output Resolution = {},").format(self.tableRes))
        elif self.spinResBox == 0.00 and selectedAoi == None:
            text.append(self.tr("Clip Output Resolution = no clip file created,"))
        else:
            text.append(self.tr("Clip Output Resolution = {},").format(self.spinResBox))
        text.append(self.tr("Output Folder = {},\n").format(self.chm_path_folder) +
        self.tr("Output Format = {},").format(selectedFormat))
        if (self.selectedcrs == '' or self.code == '' or self.code == self.input_crs):
            text.append(self.tr("Output CRS = EPSG: {},").format(self.input_crs))
        else:
            text.append(self.tr("Output CRS = {},").format(self.selectedcrs))
        text.append(self.tr("Remove values < 0 = {},").format(self.dlg.checkNegValBox.isChecked()))
        if self.spinMaxBox == 0:
            txt_max = self.tr('no threshold selected')
        else:
            txt_max = self.spinMaxBox
        text.append(self.tr("Max value threshold = {}\n").format(txt_max))
        text.append(self.tr("*** PROCESS FINISHED! ***"))
        
    def overlapLog(self, fi_ov, log_dict):
        text = self.dlg.textLog
        text.append(self.tr("WARNING!! the following campaigns have been selected:\n"))
        for key, value in log_dict.items():
            text.append("ENTE: {}".format(value[2]) + "\n" +
            "CAMPAGNA: {}".format(key) + "\n" + 
            "ANNO: {}".format(value[0]) + "\n" + 
            "RISOLUZIONE: {}".format(value[1]) + "\n")
        text.append(self.tr("It is possible to visualize the current selection on the map (zoom to selection tool)\n"))
        text.append(self.tr("Please, choose the desired CAMPAIGN in the campaign Combo Box" + "\n"))
        
    def crsButton(self):
        self.crs_select = QgsProjectionSelectionDialog()
        self.crs_select.exec_()
        self.selectedcrsdef = self.crs_select.crs()
        #print(self.selectedcrsdef)
        self.selectedcrs = self.selectedcrsdef.authid()
        #print(self.selectedcrs)
        if self.selectedcrs != '':
            self.epsg_code = self.selectedcrs.split(":")
            #print(self.epsg_code)
            self.code = self.epsg_code[1]
            #print(self.code)
        else:
            self.epsg_code = ''
            #print(self.epsg_code)
            self.code = ''
            #print(self.code)
            
    def clearButton(self):
        self.dlg.textLog.clear()
        
    def openHelpButton(self):
        if QgsSettings().value('locale/userLocale') == 'it':
            webbrowser.open('https://chm-from-lidar-manuale.readthedocs.io/it/latest/')
        elif QgsSettings().value('locale/userLocale') == 'es':
            webbrowser.open('https://chm-from-lidar-manuale.readthedocs.io/es/latest/')
        else:
            webbrowser.open('https://chm-from-lidar-manuale.readthedocs.io/en/latest/')
            
    def handleCheckBox(self):
        #self.checkNegBox = state
        if self.dlg.checkNegValBox.isChecked() == True:
            self.checkNegBox = True
            #print('check')
        else:
            self.checkNegBox = False
            #print('ucheck')
            
    def handleChmkBox(self):
        #self.checkNegBox = state
        if self.dlg.useChmBox.isChecked() == True:
            self.checkChmBox = True
            #print('check')
        else:
            self.checkChmBox = False
            #print('ucheck')
            
    def handleSpinBox(self, val):
        self.spinMaxBox = val
        #print(self.spinMaxBox)
        
    def handleResSpinBox(self, val):
        self.spinResBox = val
        #print(self.spinResBox)
        
    def handleClipName(self, val):
        self.NameClip = val
        #print(self.NameClip)
        
    def comboBoxe(self, idx):
        #print('fai qualcosa')
        self.comboIndex = idx
        #print(self.comboIndex)
        vlayer = self.dlg.comboAoiBox.currentLayer()
        # #print(self.comboIndex)
        # #print(self.comboIndex - 1)
        if self.comboIndex != 0 and self.aoiIndex != -1:
            self.dlg.resolSpinBox.setEnabled(False)
            self.dlg.resolSpinBox.setValue(0.00)
            self.spinResBox = 0.00
            #print(self.spinResBox)
            if not vlayer.selectedFeatures():
                self.dlg.checkSelFeatbox.setChecked(False)
                self.dlg.checkSelFeatbox.setEnabled(False)
                self.dlg.checkSelFeatbox.setToolTip(self.tr("No features selected in layer"))
            else:
                #print('ciao')
                self.dlg.checkSelFeatbox.setEnabled(True)
                self.dlg.checkSelFeatbox.setToolTip(self.tr("Use only selected features"))
            # self.dlg.comboAoiBox.setDisabled(True)
        elif self.aoiIndex != -1 and self.comboIndex == 0:
            #print(self.aoiIndex)
            #self.dlg.comboBox.setDisabled(True)
            #print(vlayer)
            self.dlg.resolSpinBox.setEnabled(True)
            if not vlayer.selectedFeatures():
                self.dlg.checkSelFeatbox.setChecked(False)
                self.dlg.checkSelFeatbox.setEnabled(False)
                self.dlg.checkSelFeatbox.setToolTip(self.tr("No features selected in layer"))
            else:
                #print('ciao')
                self.dlg.checkSelFeatbox.setEnabled(True)
                self.dlg.checkSelFeatbox.setToolTip(self.tr("Use only selected features"))
    
    def enteBox(self, idxe):
        #print('ente')
        self.enteIndex = idxe
        if self.enteIndex == 0:
            uniquevalues = []
            # #print(uniquevalues)
            uniqueprovider = self.lyr.dataProvider()
            fields = uniqueprovider.fields()
            id = fields.indexFromName('P_CAMPAGNA')
            uniquevalues = list(uniqueprovider.uniqueValues( id ))
            # #print(len(uniquevalues))
            # #print(uniquevalues)
            
            self.show_values = []
            for uv in uniquevalues:
                #print (uv)
                if uv != NULL and uv != '':
                    str_value = str(uv)
                    self.show_values.append(str_value)
                # #str_values = str(uv).split("\\")
                # #if len(str_values) > 1: #per percorsi regione veneto mettere 4
                    # #show_values.append(str_values[1] + ' - ' + str_values[2]) #per percorsi regione veneto mettere 5 e 6
            #print (self.show_values)
            
            self.dlg.comboBox.clear()
            self.dlg.comboBox.addItem('') #--> aggiunge una riga vuota nell'elenco della combo
            self.dlg.comboBox.addItems(sv for sv in self.show_values)
        else:
            self.show_values = []
            filter = self.dlg.comboEnteBox.currentText()
            #print (filter)
            values = [feat['P_CAMPAGNA'] for feat in self.lyr.getFeatures() if feat['ENTE'] == filter]
            list_val = set(values)
            for uv in list_val:
                if uv != '':
                    self.show_values.append(uv)
            
            self.dlg.comboBox.clear()        
            self.dlg.comboBox.addItem('') #--> aggiunge una riga vuota nell'elenco della combo
            #self.dlg.comboBox.addItems(sv for sv in self.show_values)
            self.dlg.comboBox.addItems(sv for sv in self.show_values)
        
    def AoicomboBoxe(self, aidx):
        # added check of number of vector layer
        if len(QgsProject.instance().mapLayers()) > 1:
            self.aoiIndex = aidx
        vlayer = self.dlg.comboAoiBox.currentLayer()
        #print(vlayer)
        #if self.aoiIndex != -1 and self.comboIndex == 0:
        if self.aoiIndex != -1 and self.comboIndex != 0:
            #print(self.aoiIndex)
            self.dlg.clipName.setEnabled(True)
            #print(vlayer)
            if not vlayer.selectedFeatures():
                self.dlg.checkSelFeatbox.setChecked(False)
                self.dlg.checkSelFeatbox.setEnabled(False)
                self.dlg.checkSelFeatbox.setToolTip(self.tr("No features selected in layer"))
            else:
                #print('ciao')
                self.dlg.checkSelFeatbox.setEnabled(True)
                self.dlg.checkSelFeatbox.setToolTip(self.tr("Use only selected features"))
                # # # self.selectedfeats.setChecked(1)
            # # #else:
                # # #pass
        elif self.aoiIndex != -1 and self.comboIndex == 0:
            #print(self.aoiIndex)
            #self.dlg.comboBox.setDisabled(True)
            #print(vlayer)
            self.dlg.clipName.setEnabled(True)
            self.dlg.resolSpinBox.setEnabled(True)
            if not vlayer.selectedFeatures():
                self.dlg.checkSelFeatbox.setChecked(False)
                self.dlg.checkSelFeatbox.setEnabled(False)
                self.dlg.checkSelFeatbox.setToolTip(self.tr("No features selected in layer"))
            else:
                #print('ciao')
                self.dlg.checkSelFeatbox.setEnabled(True)
                self.dlg.checkSelFeatbox.setToolTip(self.tr("Use only selected features"))
        else:
            self.dlg.comboBox.setDisabled(False)
            self.dlg.comboAoiBox.setDisabled(False)
            
    def unique(self, fi_ov): 
        # intilize a null list 
        unique_list = [] 
          
        # traverse for all elements 
        for x in fi_ov: 
            # check if exists in unique_list or not 
            if x not in unique_list: 
                unique_list.append(x) 
        # print list 
        return unique_list
        
    def calc2(self, chm_calc, chm_out_tempdir, chm_calc2):
        #print('eccolo la funzione calc2')
        #print(chm_out_tempdir)
        #print(chm_calc)
        processing.run("qgis:rastercalculator", {'EXPRESSION' : '(\"{0}@1\" > 0) * \"{0}@1\"'.format(chm_calc),
        'LAYERS' : '{}/{}.tif'.format(chm_out_tempdir.name, chm_calc),
        #'CRS' : QgsCoordinateReferenceSystem('EPSG:4326'),
        'OUTPUT': '{}/{}.tif'.format(chm_out_tempdir.name, chm_calc2)}) #output deve essere un file diverso da input
        self.chmFinalName = chm_calc2
        #self.chmFinalName2 = chm_calc2
        
    def calc3(self, chm_tname, chm_out_tempdir, chm_calc3):
        #print('eccolo la funzione calc3')
        #print(chm_out_tempdir)
        #print(chm_tname)
        processing.run("qgis:rastercalculator", {'EXPRESSION' : '(\"{0}@1\" < {1}) * \"{0}@1\" + (\"{0}@1\" >= {1}) * {1}'.format(chm_tname, self.spinMaxBox),
        'LAYERS' : '{}/{}.tif'.format(chm_out_tempdir.name, chm_tname),
        #'CRS' : QgsCoordinateReferenceSystem('EPSG:4326'),
        'OUTPUT': '{}/{}.tif'.format(chm_out_tempdir.name, chm_calc3)}) #output deve essere un file diverso da input
        self.chmFinalName = chm_calc3
        #self.chmFinalName2 = chm_calc3
        
    def checkLatlon(self, code_chm):
        # function check if CRS is projected or not
        # if is projected=0
        # if is goegraphic or latlon = 1
        osr.UseExceptions()
        srs = osr.SpatialReference()
        srs.ImportFromEPSG(int(code_chm))  # this will now raise RuntimeError for corrupt data
        text=srs.ExportToProj4()

        srs_var=text.split()

        # 0 if is projected CRS 1 if is not projected
        check_geo=0 
        i=0
        while i<len(srs_var):
           if(srs_var[i].split('=')[0]=='+proj' and srs_var[i].split('=')[1]=='longlat'):
               check_geo=1
               
           i+=1 

        #print(check_geo)
        return check_geo
        
    def latLonres(self, code_chm, ress):
        #print('sono in latlonres')
        # Input:
        # 0: EPSG
        # 1: risoluzione
        # 2: vettore (o selezione)
        path = self.chm_out_tempdir_s
        input = self.lyr
        input_res = ress
        input_epsg = code_chm
        #print(path.name)
        #print(input_epsg)
        #print(input_res)
        #inviluppo=os.path.join(path.name,'inviluppo.shp')
        centro=os.path.join(path.name,'centro_{}.shp'.format(self.rs_count))
        buffer=os.path.join(path.name,'buffer_{}.shp'.format(self.rs_count))
        buffer_r=os.path.join(path.name,'input_{}.shp'.format(self.rs_count))
        n_centro='centro'
        

        processing.run('native:meancoordinates',
        { 'INPUT' : input, 
        'OUTPUT' : centro,
        'UID' : None,
        'WEIGHT' : None }
        )

        #iface.addVectorLayer(buffer,'test')
        processing.run('native:buffer',
        { 'DISSOLVE' : False, 
        'DISTANCE' : input_res, 
        'END_CAP_STYLE' : 0, 
        'INPUT' : centro,
        'JOIN_STYLE' : 0,
        'MITER_LIMIT' : 2,
        'OUTPUT' : buffer, 
        'SEGMENTS' : 5 }
        )

        processing.run('native:reprojectlayer',
        { 'INPUT' : buffer,
        'OUTPUT' : buffer_r,
        'TARGET_CRS' : QgsCoordinateReferenceSystem('EPSG:{}'.format(input_epsg)) 
        })

        tmp_lyr=QgsVectorLayer(buffer_r,n_centro)

        #lyrCRS = tmp_lyr.crs().authid() # returns a reference to the active QgsMapLayer
        #print(lyrCRS)
        for f in tmp_lyr.getFeatures():
            #EST=f["MEAN_X"]
            #NORD=f["MEAN_Y"]
            resol = (f.geometry().boundingBox().xMaximum() - f.geometry().boundingBox().xMinimum())/2
            
            #raggio = perimeter/(pi*2)
        self.rs_count += 1
        #print("EST={},NORD={}".format(EST,NORD))
        #print(resol)
        return resol
        
    def convertRes(self, code_chm):
        if self.checkLatlon(code_chm) == 1:
            if self.spinResBox != 0.00:
                return self.latLonres(code_chm, self.spinResBox)
                #return (0.00001 * self.spinResBox)
            else:
                return self.latLonres(code_chm, self.tableRes)
                #return (0.00001 * self.tableRes)
        else:
            if self.spinResBox != 0.00:
                return self.spinResBox
            return self.tableRes
        
    def resample(self, res, chmFinalName, chm_out_tempdir, code_chm):
        chm_res_temppathfile = os.path.join(chm_out_tempdir.name, '{}_res.tif'.format(chmFinalName))
        if self.spinResBox != 0.00:
            chm_temppathfile = os.path.join(chm_out_tempdir.name, '{}.tif'.format(chmFinalName))
            #print('fai resample 1')
            #print(chm_temppathfile)
            processing.run("gdal:warpreproject", {'INPUT': chm_temppathfile,
                'SOURCE_CRS': None,
                'TARGET_CRS': 'EPSG:{}'.format(code_chm),
                'RESAMPLING': 1,
                'NODATA': None,
                'TARGET_RESOLUTION' : self.convertRes(code_chm),
                'DATA_TYPE': 0,
                'OUTPUT': chm_res_temppathfile})
            #print(chm_res_temppathfile)
            return chm_res_temppathfile

        elif len(self.unique(res)) > 1 and self.spinResBox == 0.00:
            chm_temppathfile = os.path.join(chm_out_tempdir.name, '{}.tif'.format(chmFinalName))
            #print('fai resample 2')
            processing.run("gdal:warpreproject", {'INPUT': chm_temppathfile,
                'SOURCE_CRS': None,
                'TARGET_CRS': 'EPSG:{}'.format(code_chm),
                'RESAMPLING': 1,
                'NODATA': None,
                'TARGET_RESOLUTION' : self.convertRes(code_chm),
                'DATA_TYPE': 0,
                'OUTPUT': chm_res_temppathfile})
            return chm_res_temppathfile
        else:
            #print('no resample')
            chm_temppathfile = os.path.join(chm_out_tempdir.name, '{}.tif'.format(chmFinalName))
            return chm_temppathfile
            
    def clip(self, chm_out_tempdir, selectedAoiFeats, chm_list_merge, f1, f2, clip_pathfile, sf):
        #print('eccolo la funzione clip')
        #print(chm_list_merge)
        #print(chm_out_tempdir.name)
        processing.run("gdal:merge", {'INPUT' : chm_list_merge,
            'DATA_TYPE' : 5,
            # #'CRS' : QgsCoordinateReferenceSystem('EPSG:4326'),
            'OUTPUT': '{}/merge.tif'.format(chm_out_tempdir.name)}) #output deve essere un file diverso da input
        
        merge_pathfile = os.path.join(chm_out_tempdir.name, 'merge.tif')
        
        #print(merge_pathfile)

        processing.run("gdal:cliprasterbymasklayer", {'INPUT' : merge_pathfile,
            'MASK' : selectedAoiFeats,
            'NODATA' : -9999,
            'OUTPUT': '{}/clip.tif'.format(chm_out_tempdir.name)})
        
        clip_temppathfile = os.path.join(chm_out_tempdir.name, 'clip.tif')
        clip_repr_temppathfile = os.path.join(chm_out_tempdir.name, 'clip_repr.tif')
        clip_trans_temppathfile = os.path.join(chm_out_tempdir.name, 'clip_tran{}'.format(f2))
        ####### AGGIUNGERE TUTTE LE CASISTICHE DI POST CALC PER IL CLIP ######

        if f1 == 'GeoTIFF':
            if (self.selectedcrs == '' or self.code == '' or self.code == self.input_crs):
                shutil.move(clip_temppathfile, clip_pathfile)
            else:
                #print(self.selectedcrs)
                
                processing.run("gdal:warpreproject", {'INPUT': clip_temppathfile,
                    'SOURCE_CRS': None,
                    'TARGET_CRS': self.selectedcrs,
                    'RESAMPLING': 1,
                    'NODATA': None,
                    'DATA_TYPE': 0,
                    'OUTPUT': clip_repr_temppathfile})
                
                shutil.move(clip_repr_temppathfile, clip_pathfile)    
            
        elif f1 != 'GeoTIFF':
            #print('stai salvando in un altro formato')
            if (self.selectedcrs == '' or self.code == '' or self.code == self.input_crs):
                #print('stai salvando in un altro formato con 4326')
                processing.run("gdal:translate", {'INPUT': clip_temppathfile,
                    'TARGET_CRS': clip_temppathfile,
                    'NODATA': None,
                    'COPY_SUBDATASETS': False,
                    'DATA_TYPE': 0,
                    'OUTPUT': clip_trans_temppathfile})
            else:
                #chm_warp_temppathfile = os.path.join(chm_out_tempdir.name, '{}_warp.tif'.format(chmFinalName))
            
                processing.run("gdal:warpreproject", {'INPUT': clip_temppathfile,
                    'SOURCE_CRS': None,
                    'TARGET_CRS': self.selectedcrs,
                    'RESAMPLING': 1,
                    'NODATA': None,
                    'DATA_TYPE': 0,
                    'OUTPUT': clip_repr_temppathfile})
                    
                processing.run("gdal:translate", {'INPUT': clip_repr_temppathfile,
                    'TARGET_CRS': clip_repr_temppathfile,
                    'NODATA': None,
                    'COPY_SUBDATASETS': False,
                    'DATA_TYPE': 0,
                    'OUTPUT': clip_trans_temppathfile})    
    
            for clip in os.listdir(chm_out_tempdir.name):
                if clip.startswith('clip_tran'):
                    filename, file_extension = os.path.splitext(clip)
                    file_name = clip.replace(filename, self.NameClip)
                    #print(file_name)
                    oldfilepath = os.path.join(chm_out_tempdir.name, '{}{}'.format(filename, file_extension))
                    newfilepath = os.path.join(self.chm_path_folder, '{}'.format(file_name))
                # ##text_files = [f for f in os.listdir(path) if f.endswith('.aux.xml')]
                # ##print(text_files)
                    # #print(allfilepath)
                    # #os.rename(oldfilepath, newfilepath)
                    shutil.move(oldfilepath, newfilepath)                
        
    def noop(self, *args):
        print('eccolo la funzione noop')
        
    def popComboEnte(self):
        uniqueprovider = self.lyr.dataProvider()
        fields = uniqueprovider.fields()
        unique_ente = []
        id_ente = fields.indexFromName('ENTE') 
        unique_ente = list(uniqueprovider.uniqueValues( id_ente ))

        self.ente_values = []
        for uv_e in unique_ente:
            if uv_e != NULL:
                str_value_e = str(uv_e)
                self.ente_values.append(str_value_e)
                
        self.dlg.comboEnteBox.clear()
        self.dlg.comboEnteBox.addItem('')
        self.dlg.comboEnteBox.addItems(ev for ev in self.ente_values)
        
    def pressIcon(self):
        if not self.pluginIsActive:
            self.pluginIsActive = True
            self.dlg = ChmFromLidarDialog()

            #print(self.dlg.checkNegValBox.isChecked())
            #print(self.dlg.useChmBox.isChecked())
            self.dlg.exportChmButton.clicked.connect(self.exportChmButton)
            self.dlg.crsButton.clicked.connect(self.crsButton)
            self.dlg.clearButton.clicked.connect(self.clearButton)
            self.dlg.helpButton.clicked.connect(self.openHelpButton)
            self.dlg.checkNegValBox.stateChanged.connect(self.handleCheckBox)
            self.dlg.useChmBox.stateChanged.connect(self.handleChmkBox)
            self.dlg.spinMaxValBox.valueChanged.connect(self.handleSpinBox)
            self.dlg.comboEnteBox.currentIndexChanged.connect(self.enteBox)
            self.dlg.comboBox.currentIndexChanged.connect(self.comboBoxe)
            self.dlg.comboAoiBox.currentIndexChanged.connect(self.AoicomboBoxe)
            self.dlg.resolSpinBox.valueChanged.connect(self.handleResSpinBox)
            self.dlg.clipName.textChanged.connect(self.handleClipName)
            self.dlg.pushButtonOk.clicked.connect(self.run)
            self.dlg.rejected.connect(self.closePlugin)
            
            self.prepRun()
            self.dlg.show()
        else:
            self.dlg.show()
            self.dlg.activateWindow()
    
    def prepRun(self):
        if QgsProject.instance().mapLayersByName('tile_dsm_dtm'):
            self.lyr = QgsProject.instance().mapLayersByName('tile_dsm_dtm')[0]
        else:
            path = os.path.join(self.plugin_dir, 'tile_dsm_dtm.gpkg')
            #print(path)
            lyr_tile = QgsVectorLayer(path, 'tile_dsm_dtm')
            lyr_tile.setSubsetString('"N_DTM" NOT NULL and "N_DSM" NOT NULL')
            QgsProject.instance().addMapLayers([lyr_tile])
            self.lyr = QgsProject.instance().mapLayersByName('tile_dsm_dtm')[0]
        

        self.popComboEnte()
        
        #print(self.dlg.comboBox.currentIndex()) #--> restituisce l'indice della riga selezionata
        
        #self.dlg.comboAoiBox.clear()
        self.dlg.comboAoiBox.setFilters(QgsMapLayerProxyModel.PolygonLayer)
        self.dlg.comboAoiBox.setCurrentIndex(-1)
        #self.dlg.comboAoiBox.addItem('ciao')
        #print(self.dlg.comboAoiBox.currentIndex())
        
        
        #gdal.AllRegister()
        self.raster_format = []
        for i in range(gdal.GetDriverCount()):
            drv = gdal.GetDriver(i)
            drv_meta = drv.GetMetadata()
            #print (drv_meta)
            if 'DMD_EXTENSION' in drv_meta:
                if 'DCAP_RASTER' in drv_meta: 
                #print( "{}: .{}".format(drv.LongName, drv_meta['DMD_EXTENSION']))
                    self.raster_format.append( "{}: .{}".format(drv.LongName, drv_meta['DMD_EXTENSION']))
        
        self.dlg.comboFormatBox.clear()
        # Populate the comboBox with names of all the loaded layers
        self.dlg.comboFormatBox.addItems(ext for ext in self.raster_format)
        self.dlg.comboFormatBox.setCurrentIndex(self.raster_format.index('GeoTIFF: .tif'))
        #self.dlg.show()

        
    def closePlugin(self):
        """Cleanup necessary items here when plugin dockwidget is closed"""

        print("** CLOSING Plugin")

        self.dlg.exportChmButton.clicked.disconnect(self.exportChmButton)
        self.dlg.crsButton.clicked.disconnect(self.crsButton)
        self.dlg.clearButton.clicked.disconnect(self.clearButton)
        self.dlg.helpButton.clicked.disconnect(self.openHelpButton)
        self.dlg.spinMaxValBox.valueChanged.disconnect(self.handleSpinBox)
        self.dlg.checkNegValBox.stateChanged.disconnect(self.handleCheckBox)
        self.dlg.useChmBox.stateChanged.disconnect(self.handleChmkBox)
        self.dlg.comboBox.currentIndexChanged.disconnect(self.comboBoxe)
        self.dlg.comboEnteBox.currentIndexChanged.disconnect(self.enteBox)
        self.dlg.comboAoiBox.currentIndexChanged.disconnect(self.AoicomboBoxe)
        self.dlg.resolSpinBox.valueChanged.disconnect(self.handleResSpinBox)
        self.dlg.clipName.textChanged.disconnect(self.handleClipName)
        self.dlg.pushButtonOk.clicked.disconnect(self.run)
        self.dlg.rejected.disconnect(self.closePlugin)
        # remove this statement if dockwidget is to remain
        # for reuse if plugin is reopened
        # Commented next statement since it causes QGIS crashe
        # when closing the docked window:
        # self.dockwidget.deleteLater()
        # self.dockwidget = None

        self.pluginIsActive = False
        self.selectedcrs = ''
        self.chmFinalName = ''
        self.chm_path_folder = ''
        self.input_crs = ''
        self.checkNegBox = True
        self.checkChmBox = False
        self.spinMaxBox = 0
        self.comboIndex = 0
        self.enteIndex = 0
        self.aoiIndex = -1
        self.spinResBox = 0.00
        self.tableRes = 0.00
        self.NameClip = 'clip'
        #self.chm_out_tempdir_s = ''
        
        self.raster_format = []
        self.show_values = []
        self.ente_values = []
        self.lyr = ''
        self.rs_count = 0
        
        if self.chm_out_tempdir_s != '':
            self.chm_out_tempdir_s.cleanup()

        self.chm_out_tempdir_s = ''

        from qgis.utils import reloadPlugin
        reloadPlugin("ChmFromLidar")
        #print(self.checkNegBox)
        #print(self.dlg.comboBox.currentIndex())
        #print(self.dlg.comboAoiBox.currentIndex())
        
    def Calc(self, dsm_name, dtm_name, chm_out_tempdir, chm_fname, lyr_dsm, lyr_dtm, dsm_pathfile, dtm_pathfile):
        # entries = []
        # ras1 = QgsRasterCalculatorEntry()
        # ras1.ref = '{}@1'.format(dsm_name[0])
        # ras1.raster = lyr_dsm
        # ras1.bandNumber = 1
        # entries.append(ras1)
        # # # #print(ras1)

        # ras2 = QgsRasterCalculatorEntry()
        # ras2.ref = '{}@1'.format(dtm_name[0])
        # ras2.raster = lyr_dtm
        # ras2.bandNumber = 1
        # entries.append(ras2)
        
        chm_calc = '{}_calc'.format(chm_fname)
        chm_calc2 = '{}_calc2'.format(chm_fname)
        chm_calc3 = '{}_calc3'.format(chm_fname)
        
        #directory = 'C:/Users/user/Documents'
        #print(dsm_pathfile)
        #print(dtm_pathfile)
        #print(dsm_name[0])
        #print(dtm_name[0])
        #print(sf["SR_EPSG"])
        #calc = QgsRasterCalculator('{}@1 - {}@1'.format(dsm_name[0], dtm_name[0]), '{}/{}.tif'.format(chm_out_tempdir.name, chm_calc), 'GTiff', lyr_dsm.extent(), lyr_dsm.width(), lyr_dsm.height(), entries)
        #calc.processCalculation()
        processing.run("qgis:rastercalculator", {'EXPRESSION' : '\"{}_dsm@1\" - \"{}_dtm@1\"'.format(dsm_name[0], dtm_name[0]),
        'LAYERS' : [lyr_dsm, lyr_dtm],
        # 'CELLSIZE' : 0,
        # 'EXTENT' : None,
        'CRS' : 'EPSG:{}'.format(self.input_crs),
        'OUTPUT': '{}/{}.tif'.format(chm_out_tempdir.name, chm_calc)})
        #print(chm_out_tempdir)
        #print(chm_calc)
        
        self.chmFinalName = chm_calc
        #self.chmFinalName2 = chm_calc
        
        self.enableCalc2[self.checkNegBox](chm_calc, chm_out_tempdir, chm_calc2)
        if self.checkNegBox == True:
            self.enableCalc3[self.spinMaxBox > 0](chm_calc2, chm_out_tempdir, chm_calc3)
        else:
            self.enableCalc3[self.spinMaxBox > 0](chm_calc, chm_out_tempdir, chm_calc3)

        
    def postCalc(self, chm_out_tempdir, chmFinalName, chm_pathfile, f1, sf, f2, chm_fname):
        chm_temppathfile = os.path.join(chm_out_tempdir.name, '{}.tif'.format(chmFinalName))
        chm_warp_temppathfile = os.path.join(chm_out_tempdir.name, '{}_warp.tif'.format(chmFinalName))
        chm_trans_temppathfile = os.path.join(chm_out_tempdir.name, '{}_trans{}'.format(chmFinalName, f2))
        if f1 == 'GeoTIFF':
            #print('stai salvando in geotif')
            #print(f2)
            if (self.selectedcrs == '' or self.code == '' or self.code == self.input_crs):
                chm_temppathfile_copy = os.path.join(chm_out_tempdir.name, '{}_copy.tif'.format(chmFinalName))
                #print('sono qui')
                copyfile(chm_temppathfile, chm_temppathfile_copy)
                shutil.move(chm_temppathfile_copy, chm_pathfile)
                
            #elif self.code != sf["SR_EPSG"] or self.code != self.epsg_cam:
            else:
                #print(self.selectedcrs)

                processing.run("gdal:warpreproject", {'INPUT': chm_temppathfile,
                    'SOURCE_CRS': None,
                    'TARGET_CRS': self.selectedcrs,
                    'RESAMPLING': 1,
                    'NODATA': None,
                    'DATA_TYPE': 0,
                    'OUTPUT': chm_warp_temppathfile})

                shutil.move(chm_warp_temppathfile, chm_pathfile)
                #print(chm_temppathfile)   
        elif f1 != 'GeoTIFF':
            #print('stai salvando in un altro formato')
            if (self.selectedcrs == '' or self.code == '' or self.code == self.input_crs):
                #print('stai salvando in un altro formato con 4326')
            
                processing.run("gdal:translate", {'INPUT': chm_temppathfile,
                    'TARGET_CRS': chm_temppathfile,
                    'NODATA': None,
                    'COPY_SUBDATASETS': False,
                    'DATA_TYPE': 0,
                    'OUTPUT': chm_trans_temppathfile})
                
                #chm_transprj_temppathfile = os.path.join(chm_out_tempdir.name, '{}_trans.prj'.format(chmFinalName))
                #chm_transprj_pathfile = os.path.join(chm_out_dir, '{}.prj'.format(chm_fname))
                
                #shutil.move(chm_trans_temppathfile, chm_pathfile)
                    
            #elif self.code != sf["SR_EPSG"]:
            else:
                #chm_warp_temppathfile = os.path.join(chm_out_tempdir.name, '{}_warp.tif'.format(chmFinalName))
            
                processing.run("gdal:warpreproject", {'INPUT': chm_temppathfile,
                    'SOURCE_CRS': None,
                    'TARGET_CRS': self.selectedcrs,
                    'RESAMPLING': 1,
                    'NODATA': None,
                    'DATA_TYPE': 0,
                    'OUTPUT': chm_warp_temppathfile})
                    
                processing.run("gdal:translate", {'INPUT': chm_warp_temppathfile,
                    'TARGET_CRS': chm_warp_temppathfile,
                    'NODATA': None,
                    'COPY_SUBDATASETS': False,
                    'DATA_TYPE': 0,
                    'OUTPUT': chm_trans_temppathfile})
                    
            for file in os.listdir(chm_out_tempdir.name):
                if file.startswith('{}_trans'.format(chmFinalName)):
                    filename, file_extension = os.path.splitext(file)
                    file_name = file.replace(filename, chm_fname)
                    #print(file_name)
                    oldfilepath = os.path.join(chm_out_tempdir.name, '{}{}'.format(filename, file_extension))
                    newfilepath = os.path.join(self.chm_path_folder, '{}'.format(file_name))
                # ##text_files = [f for f in os.listdir(path) if f.endswith('.aux.xml')]
                # ##print(text_files)
                    # #print(allfilepath)
                    # #os.rename(oldfilepath, newfilepath)
                    shutil.move(oldfilepath, newfilepath)

    
    def run(self):
        #print('sono in run')
        self.dlg.textLog.setText(self.tr('PROCESS STARTED...\n'))
        QCoreApplication.processEvents()
        #directory = 'C:/Users/user/Documents'
        """Run method that performs all the real work"""
        #self.dlg.checkNegValBox.setChecked(False)
        #print(self.dlg.checkNegValBox.isChecked())
        #print(self.selectedcrs)

        if self.lyr.selectedFeatureCount() > 0:
            self.lyr.removeSelection()
            #print('selection removed')
        else:
            print('No feature selected')

        if self.NameClip == 'clip' and self.aoiIndex != -1:
            self.dlg.textLog.append(self.tr('WARNING: no output clip name has been selected, the default one will be used\n'))
        
        if self.chm_path_folder == '':
            self.dlg.textLog.append(self.tr('ERROR: no output folder has been selected\n'))
            return
        
        result = True
        # See if OK was pressed
        if result:
            #self.dlg.show()
            #print(result)
            #print(self.checkNegBox)

            if self.chm_out_tempdir_s == '':
                self.chm_out_tempdir_s = tempfile.TemporaryDirectory()
            else:
                self.chm_out_tempdir_s.cleanup()
                self.chm_out_tempdir_s = tempfile.TemporaryDirectory()
            
            chm_out_tempdir = self.chm_out_tempdir_s
            #print(chm_out_tempdir)
            #print(chm_out_tempdir.name)
            
            selectedFormatIndex = self.dlg.comboFormatBox.currentIndex()
            #print (selectedFormatIndex)
            selectedFormat = self.raster_format[selectedFormatIndex]
            #print (selectedFormat)
            format = selectedFormat.split(": ")
            f1 = format[0]
            f2 = format[1]
            
            #campaignIndex = self.dlg.comboBox.currentIndex()
            #print (campaignIndex)
            #selectedCampaignIndex = campaignIndex - 1
            selectedCampaign = self.show_values[self.comboIndex - 1]
            #print (selectedCampaign)
            
            #aoiIndex = self.dlg.comboAoiBox.currentIndex()
            #print (aoiIndex)
            #selectedAoiIndex = aoiIndex - 1
            selectedAoi = self.dlg.comboAoiBox.currentLayer()
            #print(selectedAoi)
            
            if self.dlg.checkSelFeatbox.isChecked():
                selectedAoiFeats = QgsProcessingFeatureSourceDefinition(selectedAoi.id(), True)
            else:
                selectedAoiFeats = selectedAoi
            
            #print (selectedAoi)
            # search = selectedLayer.split(" - ")
            # s1 = search[0]
            # s2 = search[1]
            # print(s1)
            # print(s2)
            
            #selectedcrsdef = self.crs_select.crs()
            #selectedcrs = selectedcrsdef.authid()
            #epsg_code = self.selectedcrs.split(":")
            #code = epsg_code[1]
            #intersec_layer = QgsProcessingFeatureSourceDefinition(selectedAoi.id(), True)
            #fids = []
            warning_string = ''
            chm_list_merge = []
            self.dlg.textLog.append(self.tr('SELECTING TILES...\nThe process may take some time..\n'))
            QCoreApplication.processEvents()
            for f in self.lyr.getFeatures():
                #print(f["P_DTM"])
                if f["P_DTM"] == NULL and f["P_DSM"] != NULL and f["P_CAMPAGNA"] != NULL:
                    if selectedCampaign in f["P_CAMPAGNA"]:
                        #print('no DTM found')
                        warning_string = self.tr('{} No DTM found for tile with fid {}\n').format(warning_string, f["fid"])
                elif f["P_DSM"] == NULL and f["P_DTM"] != NULL and f["P_CAMPAGNA"] != NULL:
                    if selectedCampaign in f["P_CAMPAGNA"]:
                        #print('no DSM found')
                        warning_string = self.tr('{} No DSM found for tile with fid {}\n').format(warning_string, f["fid"])
                elif f["P_DSM"] == NULL and f["P_DTM"] == NULL and f["P_CAMPAGNA"] != NULL:
                    if selectedCampaign in f["P_CAMPAGNA"]:
                        #print('no DSM and DTM found')
                        warning_string = self.tr('{} No DSM and DTM found for tile with fid {}\n').format(warning_string, f["fid"])
                elif f["P_CAMPAGNA"] == NULL:
                    #if selectedCampaign in f["P_CAMPAGNA"]:
                    print('no CAMPAGNA found')
                    #warning_string = '{} No CAMPAIGN found for tile with fid {}\n'.format(warning_string, f["fid"])
                    
                else:
                    if self.comboIndex != 0:
                        if selectedCampaign in f["P_CAMPAGNA"] and self.aoiIndex == -1:
                            # print('trovati')
                                self.lyr.select(f.id())
                                self.tableRes = f["RISOLUZ_RA"]
                                #print(self.tableRes)
                            #fids.append(f.id())
                        elif selectedCampaign in f["P_CAMPAGNA"] and self.aoiIndex != -1:
                            self.tableRes = f["RISOLUZ_RA"]
                            #print(self.tableRes)
                            if self.dlg.checkSelFeatbox.isChecked():
                                for fAoi in selectedAoi.getSelectedFeatures():
                                    if f.geometry().intersects(fAoi.geometry()):
                                        self.lyr.select(f.id())
                            else:
                                for fAoi in selectedAoi.getFeatures():
                                    if f.geometry().intersects(fAoi.geometry()):
                                        self.lyr.select(f.id())
                    elif self.aoiIndex != -1 and self.comboIndex == 0:
                        if self.dlg.checkSelFeatbox.isChecked():
                            for fAoi in selectedAoi.getSelectedFeatures():
                                if f.geometry().intersects(fAoi.geometry()):
                                    self.lyr.select(f.id())
                        else:
                            for fAoi in selectedAoi.getFeatures():
                                if f.geometry().intersects(fAoi.geometry()):
                                    self.lyr.select(f.id())
                                   
            self.dlg.textLog.append(self.tr('{}').format(warning_string))
            self.dlg.textLog.append(self.tr('{} tiles have been selected.\n').format(self.lyr.selectedFeatureCount()))
            
            if self.lyr.selectedFeatureCount() == 0:
                self.dlg.textLog.append(self.tr('ATTENTION! No tiles have been selected.\n' +
                'It is probably due to one of the following reasons:\n' +
                '1 - the selected AOI does not intersect the selected Campaign;\n' +
                '2 - P_DTM and/or P_DSM fields could be empty;\n' +
                '3 - P_CAMPAGNA field could be empty;\n' +
                'Check the input parameters.'))
                return
            
            fi_ov = []
            fi2_ov = []
            fi_res = []
            fi_an = []
            fi_epsg = []
            fi_ente = []
            log_dict = {}
            if self.aoiIndex != -1 and self.comboIndex == 0:
                #fi2_res = []
                ii = []
                for  f in self.lyr.getSelectedFeatures():
                    ii.append(f.id())
                    i = f.id()
                    #break
                #i = ii[0]
                #print(ii)
                #print(i)
                for fi in self.lyr.getSelectedFeatures():
                    fi_ov.append(fi["P_CAMPAGNA"])
                    fi_res.append(fi["RISOLUZ_RA"])
                    fi_an.append(fi["ANNO"])
                    fi_epsg.append(fi["SR_EPSG"])
                    fi_ente.append(fi["ENTE"])
                    #print(fi["ANNO"])
                    log_dict[fi_ov[-1]] = (fi_an[-1], fi_res[-1], fi_ente[-1])
                    i = fi.id()
                #    if f.id() == i:
                    for fi2 in self.lyr.getSelectedFeatures():
                        #f_ov.append(f["P_CAMPAGNA"]) #qui carico tutto le campagna che seleziono
                        #f_res.append(f["RISOLUZ_RA"])
                        if fi2.id() > i:
                            if fi.geometry().intersects(fi2.geometry()):
                                intersection = fi.geometry().intersection(fi2.geometry())
                                if intersection.area() > 0:
                                    fi2_ov.append(fi["P_CAMPAGNA"]) #qui carico tutto le campagna che seleziono e che si sovrappongono fra loro
                                    fi2_ov.append(fi2["P_CAMPAGNA"])
                                    #fi2_res.append(fi["RISOLUZ_RA"]) #qui carico tutto le campagna che seleziono e che si sovrappongono fra loro
                                    #fi2_res.append(fi2["RISOLUZ_RA"])
                                else:
                                    print('sonoadiacenti')
                    #i = i+1
                #   else:

                #print(self.unique(fi_ov))
                #print(len(self.unique(fi_ov)))
                if len(self.unique(fi_ov)) == 1:
                    self.tableRes = self.unique(fi_res)[0]
                    #print('fai tutto')
                    epsg_cam = self.unique(fi_epsg)[0]
                    if self.spinResBox != 0.00 and self.tableRes > self.spinResBox:
                        #print(self.spinResBox)
                        self.dlg.textLog.append(self.tr("WARNING: a resolution lower than the one of the input data has been selected\n"))
                elif len(self.unique(fi_ov)) > 1 and len(fi2_ov) == 0:
                    self.tableRes = max(fi_res)
                    if len(self.unique(fi_epsg)) == 1:
                        epsg_cam = self.unique(fi_epsg)[0]
                    elif len(self.unique(fi_epsg)) > 1 and self.selectedcrs == '':
                        self.dlg.textLog.append(self.tr("WARNING: different campaigns with different CRS have been selected:\n"))
                        kk = 0
                        while kk < len(self.unique(fi_epsg)):
                            self.dlg.textLog.append(self.tr("EPSG: {}\n").format(self.unique(fi_epsg)[kk]))
                            kk += 1
                        self.dlg.textLog.append(self.tr("Please, select the output CRS.\n"))
                        return

                    if self.spinResBox != 0.00 and self.tableRes > self.spinResBox:
                        #print(self.spinResBox)
                        self.dlg.textLog.append(self.tr("WARNING: a resolution lower than the one of the input data has been selected\n"))
                elif len(self.unique(fi_ov)) > 1 and len(fi2_ov) > 1:
                    self.overlapLog(fi_ov, log_dict)
                    return        
               
                                    
                        # processing.run("native:selectbylocation", {'INPUT': lyr,
                        # 'PREDICATE': [0],
                        # 'INTERSECT': selectedAoiFeats,
                        # 'METHOD': 0})
                #else:
                    #print('NO')
            #print(fids)
            #creates layer group
            root = QgsProject.instance().layerTreeRoot()
            group_lyr = root.insertGroup(0, '{}'.format(datetime.now().strftime("%Y%m%d_%H%M%S")))
            
            if self.dlg.clipName.isEnabled() == True:
                name_new_lyr = '{}_{}_selectedTiles'.format(self.NameClip, datetime.now().strftime("%Y%m%d_%H%M%S"))
            else:
                if selectedCampaign.find('\\') != -1:
                    name_new_lyr = '{}_{}_selectedTiles'.format(selectedCampaign.replace('\\', '_'), datetime.now().strftime("%Y%m%d_%H%M%S"))
                elif selectedCampaign.find('/') != -1:
                    name_new_lyr = '{}_{}_selectedTiles'.format(selectedCampaign.replace('/', '_'), datetime.now().strftime("%Y%m%d_%H%M%S"))
                else:
                    name_new_lyr = '{}_{}_selectedTiles'.format(selectedCampaign, datetime.now().strftime("%Y%m%d_%H%M%S"))
                    
            name_new_shp = '{}.shp'.format(name_new_lyr)
            processing.run("native:saveselectedfeatures", { 'INPUT' : self.lyr, 
            'OUTPUT' : '{}/{}'.format(self.chm_path_folder, name_new_shp)})
            
            new_lyr_tile = QgsVectorLayer(os.path.join(self.chm_path_folder, name_new_shp), name_new_lyr)
            QgsProject.instance().addMapLayers([new_lyr_tile], False)
            group_lyr.insertLayer(-1, new_lyr_tile)
            self.dlg.textLog.append(self.tr('COMPUTING CHM...\nThe process may take some time..\n'))
            QCoreApplication.processEvents()
            chm_res = []
           
            new_lyr_tile.startEditing()
            i_id = 0
            pos = 0
            count_tile = 0
            for sf in self.lyr.getSelectedFeatures():
                count_tile += 1
                self.dlg.textLog.append(self.tr('Processing tile n. {} of {}\n').format(count_tile, self.lyr.selectedFeatureCount()))
                check_dsm_zip = 0
                check_dtm_zip = 0
                sf_id = sf.id()
                pfield_id = sf.fields().indexFromName('P_CHM')
                nfield_id = sf.fields().indexFromName('N_CHM')
                efield_id = sf.fields().indexFromName('EPSG_CHM')
                chm_out_dir = self.chm_path_folder
                if sf["P_CHM"] != NULL and sf["N_CHM"]!= NULL and self.checkChmBox == False:
                    #print('uso i CHM')
                    inchm_pathfile = os.path.join(sf["P_CHM"], sf["N_CHM"])
                    if os.path.isfile(inchm_pathfile):
                        self.dlg.textLog.append(self.tr("CHM file {} has been found and it will be used for the next computation steps.\n").format(sf["N_CHM"]))
                        QCoreApplication.processEvents()
                        try:
                            chm_file_epsg = gdal.Info(inchm_pathfile, format='json')['coordinateSystem']['wkt'].rsplit('"EPSG",', 1)[-1].split(']')[0]
                            if chm_file_epsg == sf["EPSG_CHM"] or chm_file_epsg == '':
                                self.input_crs = sf["EPSG_CHM"]
                                inchm_name = sf["N_CHM"].split(".")
                                chm_fname = inchm_name[0]
                                chm_pathfile = os.path.join(chm_out_dir, '{}{}'.format(chm_fname, f2))
                                chm_calc = '{}_calc'.format(inchm_name[0])
                                self.chmFinalName = chm_calc
                                inchm_pathfile_copy = os.path.join(chm_out_tempdir.name, chm_calc)                        
                                processing.run("gdal:translate", {'INPUT': inchm_pathfile,
                                'TARGET_CRS': 'EPSG:{}'.format(self.input_crs),
                                'NODATA': None,
                                'COPY_SUBDATASETS': False,
                                'DATA_TYPE': 0,
                                'OUTPUT': '{}.tif'.format(inchm_pathfile_copy)})
                                chm_calc2 = '{}_calc2'.format(chm_fname)
                                chm_calc3 = '{}_calc3'.format(chm_fname)
                                self.enableCalc2[self.checkNegBox](chm_calc, chm_out_tempdir, chm_calc2)
                                if self.checkNegBox == True:
                                    self.enableCalc3[self.spinMaxBox > 0](chm_calc2, chm_out_tempdir, chm_calc3)
                                else:
                                    self.enableCalc3[self.spinMaxBox > 0](chm_calc, chm_out_tempdir, chm_calc3)
                                    
                                self.postCalc(chm_out_tempdir, self.chmFinalName, chm_pathfile, f1, sf, f2, chm_fname)
                                lyr_chm = QgsRasterLayer(chm_pathfile, chm_fname)
                                chm_crs = lyr_chm.crs().authid()
                                code_chm = chm_crs.split(':')
                                
                                chm_res_pathfile = self.resample(fi_res, self.chmFinalName, chm_out_tempdir, code_chm[1])
                                

                                
                                for xml in os.listdir(chm_out_dir):
                                    #if xml.endswith('{}{}.aux.xml'.format(chm_fname, f2)):
                                    if xml.endswith('.xml'):
                                        xmlpath = os.path.join(chm_out_dir, xml)
                                    # ##text_files = [f for f in os.listdir(path) if f.endswith('.aux.xml')]
                                    # ##print(text_files)
                                        # print(xmlpath)
                                        os.remove(xmlpath)
                                
                                new_lyr_tile.changeAttributeValue(i_id, efield_id, code_chm[1])
                                new_lyr_tile.changeAttributeValue(i_id, pfield_id, chm_out_dir)
                                new_lyr_tile.changeAttributeValue(i_id, nfield_id, "{}{}".format(chm_fname, f2))
                                
                                i_id += 1
                                
                                # print(chm_pathfile)
                                # print(chm_fname)
                                QgsProject.instance().addMapLayers([lyr_chm], False)
                                group_lyr.insertLayer(pos, lyr_chm)
                                pos += 1
                                chm_list_merge.append(chm_res_pathfile)
                                #print(chm_list_merge)
                            else:
                                self.dlg.textLog.append(self.tr("WARNING: CHM file {} has a different CRS than the one specified in the attribute table. Try to use the Recompute CHM checkbox.\n").format(sf["N_CHM"]))
                                QCoreApplication.processEvents()
                        except:
                            self.dlg.textLog.append(self.tr("WARNING: CHM file {} has not a standard gdal format. Try to use the Recompute CHM checkbox.\n").format(sf["N_CHM"]))
                            QCoreApplication.processEvents()
                            
                    else:
                        self.dlg.textLog.append(self.tr("WARNING: CHM file {} not found. Try to use the Recompute CHM checkbox.\n").format(sf["N_CHM"]))
                        QCoreApplication.processEvents()

                else:
                    self.input_crs = sf["SR_EPSG"]
                    if sf["COMPRESSIO"] == 'zip':
                        dsm_zip_path = sf["P_BASE"] + sf["P_CAMPAGNA"] + sf["P_DSM"]
                        dsm_zip_name = sf["N_DSM"].split(".")
                        dsm_fzip_name = dsm_zip_name[0] + '.' + dsm_zip_name[1].replace(dsm_zip_name[1], 'zip')
                        #print(dsm_fzip_name)
                        dsm_zip_pathfile = os.path.join(dsm_zip_path, dsm_fzip_name)
                        if zipfile.is_zipfile(dsm_zip_pathfile):
                            extr_dsm = zipfile.ZipFile(dsm_zip_pathfile)
                            if len(extr_dsm.namelist()) > 0:
                                extr_dsm.extractall(dsm_zip_path)
                                check_dsm_zip = 1
                                dsm_unzipped = []
                                for dsm_unz in extr_dsm.namelist():
                                    dsm_unzipped.append(dsm_unz)
                        dtm_zip_path = sf["P_BASE"] + sf["P_CAMPAGNA"] + sf["P_DTM"]
                        dtm_zip_name = sf["N_DTM"].split(".")
                        dtm_fzip_name = dtm_zip_name[0] + '.' + dtm_zip_name[1].replace(dtm_zip_name[1], 'zip')
                        #print(dtm_fzip_name)
                        dtm_zip_pathfile = os.path.join(dtm_zip_path, dtm_fzip_name)
                        if zipfile.is_zipfile(dtm_zip_pathfile):
                            extr_dtm = zipfile.ZipFile(dtm_zip_pathfile)
                            if len(extr_dtm.namelist()) > 0:
                                extr_dtm.extractall(dtm_zip_path)
                                check_dtm_zip = 1
                                dtm_unzipped = []
                                for dtm_unz in extr_dtm.namelist():
                                    dtm_unzipped.append(dtm_unz)
                            
                    dsm_path = sf["P_BASE"] + sf["P_CAMPAGNA"] + sf["P_DSM"]
                    dsm_pathfile = os.path.join(dsm_path, sf["N_DSM"])
                    dtm_path = sf["P_BASE"] + sf["P_CAMPAGNA"] + sf["P_DTM"]
                    dtm_pathfile = os.path.join(dtm_path, sf["N_DTM"])
                    #print(dtm_pathfile)
                    dsm_name = sf["N_DSM"].split(".")
                    dtm_name = sf["N_DTM"].split(".")
                    dsm_exist = os.path.isfile(dsm_pathfile)
                    dtm_exist = os.path.isfile(dtm_pathfile)
                    self.dlg.textLog.append(self.tr("The DSM file is: {}\n").format(dsm_pathfile))
                    QCoreApplication.processEvents()
                    self.dlg.textLog.append(self.tr("The DTM file is: {}\n").format(dtm_pathfile))
                    QCoreApplication.processEvents()
                    if dsm_exist == True and dtm_exist == True:
                        try:
                            #print('sono nel try')
                            #modificare l'if sotto perchè su un layer non ha sr definito come nel caso degli asci non trova ['coordinateSystem'] e quindi dà un errore per cui esce dal try
                            dtm_file_info = gdal.Info(dtm_pathfile, format='json')
                            dsm_file_info = gdal.Info(dsm_pathfile, format='json')
                            if 'coordinateSystem' in dtm_file_info:
                                dtm_file_coord = gdal.Info(dtm_pathfile, format='json')['coordinateSystem']['wkt']
                                if (dtm_file_coord.find('"EPSG","') != -1) or (dtm_file_coord == ''):
                                    dtm_file_epsg = dtm_file_coord.rsplit('"EPSG","', 1)[-1].split('"')[0]
                                else:
                                    dtm_file_epsg = dtm_file_coord.rsplit('"EPSG",', 1)[-1].split(']')[0] 
                            else:
                                dtm_file_epsg = ''
                            if 'coordinateSystem' in dsm_file_info:
                                dsm_file_coord = gdal.Info(dsm_pathfile, format='json')['coordinateSystem']['wkt']
                                if (dsm_file_coord.find('"EPSG","') != -1) or (dsm_file_coord == ''):
                                    dsm_file_epsg = dsm_file_coord.rsplit('"EPSG","', 1)[-1].split('"')[0]
                                else:
                                    dsm_file_epsg = dsm_file_coord.rsplit('"EPSG",', 1)[-1].split(']')[0]
                            else:
                                dsm_file_epsg = ''
                            #print(dtm_file_epsg)
                            if (dtm_file_epsg == sf["SR_EPSG"] and dsm_file_epsg == sf["SR_EPSG"]) or (dtm_file_epsg == '' and dsm_file_epsg == '') or (dtm_file_epsg == '' and dsm_file_epsg == sf["SR_EPSG"]) or (dsm_file_epsg == '' and dtm_file_epsg == sf["SR_EPSG"]):
                                #print('sono nel if')
                                ds = gdal.Open(dsm_pathfile)
                                #print('file aperto1')
                                # added suffix to dsm name to avoid errors in case dsm and dtm file have the same name
                                dsm_temp = os.path.join(chm_out_tempdir.name, '{}_dsm.tif'.format(dsm_name[0]))
                                ds = gdal.Translate(dsm_temp, ds, outputSRS = 'EPSG:{}'.format(self.input_crs))
                                ds = None

                                ds = gdal.Open(dtm_pathfile)
                                #print('file aperto2')
                                # added suffix to dtm name to avoid errors in case dsm and dtm file have the same name
                                dtm_temp = os.path.join(chm_out_tempdir.name, '{}_dtm.tif'.format(dtm_name[0]))
                                ds = gdal.Translate(dtm_temp, ds, outputSRS = 'EPSG:{}'.format(self.input_crs))
                                ds = None
                                lyr_dsm = QgsRasterLayer(dsm_temp, '{}_dsm.tif'.format(dsm_name[0]))
                                lyr_dtm = QgsRasterLayer(dtm_temp, '{}_dtm.tif'.format(dtm_name[0]))
                                #QgsProject.instance().addMapLayers([lyr_dsm])
                                #QgsProject.instance().addMapLayers([lyr_dtm])
                                #chm_out_dir = self.chm_path_folder
                                chm_out_name = sf["N_DTM"].split(".")
                                #print(chm_out_name[0])
                                if 'DTM' in chm_out_name[0]:
                                    chm_fname = chm_out_name[0].replace('DTM', 'CHM')
                                    #print(chm_fname)
                                elif 'dtm' in chm_out_name[0]:
                                    chm_fname = chm_out_name[0].replace('dtm', 'chm')
                                elif 'ground' in chm_out_name[0]:
                                    chm_fname = chm_out_name[0].replace('ground', 'chm')
                                else:
                                    chm_fname = chm_out_name[0] + '_CHM'
                                    
                                chm_pathfile = os.path.join(chm_out_dir, '{}{}'.format(chm_fname, f2))
                                #print(chm_pathfile)
                                
                                
                                self.Calc(dsm_name, dtm_name, chm_out_tempdir, chm_fname, lyr_dsm, lyr_dtm, dsm_pathfile, dtm_pathfile)
                                self.postCalc(chm_out_tempdir, self.chmFinalName, chm_pathfile, f1, sf, f2, chm_fname)
                                lyr_chm = QgsRasterLayer(chm_pathfile, chm_fname)
                                chm_crs = lyr_chm.crs().authid()
                                code_chm = chm_crs.split(':')
                                
                                chm_res_pathfile = self.resample(fi_res, self.chmFinalName, chm_out_tempdir, code_chm[1])
                                

                                
                                for xml in os.listdir(chm_out_dir):
                                    #if xml.endswith('{}{}.aux.xml'.format(chm_fname, f2)):
                                    if xml.endswith('.xml'):
                                        xmlpath = os.path.join(chm_out_dir, xml)
                                    # ##text_files = [f for f in os.listdir(path) if f.endswith('.aux.xml')]
                                    # ##print(text_files)
                                        # print(xmlpath)
                                        os.remove(xmlpath)
                                        
                                
                                new_lyr_tile.changeAttributeValue(i_id, efield_id, code_chm[1])
                                new_lyr_tile.changeAttributeValue(i_id, pfield_id, chm_out_dir)
                                new_lyr_tile.changeAttributeValue(i_id, nfield_id, "{}{}".format(chm_fname, f2))
                                
                                i_id += 1
                                
                                # print(chm_pathfile)
                                # print(chm_fname)
                                QgsProject.instance().addMapLayers([lyr_chm], False)
                                group_lyr.insertLayer(pos, lyr_chm)
                                pos += 1
                                chm_list_merge.append(chm_res_pathfile)
                                #print(chm_list_merge)
                            else:
                                self.dlg.textLog.append(self.tr("WARNING: DSM file {} and/or DTM file {} have a different CRS than the one specified in the attribute table. The CHM won't be computed.\n").format(sf["N_DSM"], sf["N_DTM"]))
                                QCoreApplication.processEvents()
                        except:
                            self.dlg.textLog.append(self.tr("WARNING: DSM file {} and/or DTM file {} have not a standard gdal format. Unable to open them.\n").format(sf["N_DSM"], sf["N_DTM"]))
                            QCoreApplication.processEvents()
                            
                    else:
                        if dsm_exist == False and dtm_exist == True:
                            self.dlg.textLog.append(self.tr("WARNING: DSM file {} not found. The related CHM will not be computed.\n").format(sf["N_DSM"]))
                            QCoreApplication.processEvents()
                        elif dtm_exist == False and dsm_exist == True:
                            self.dlg.textLog.append(self.tr("WARNING: DTM file {} not found. The related CHM will not be computed.\n").format(sf["N_DTM"]))
                            QCoreApplication.processEvents()
                        elif dsm_exist == False and dtm_exist == False:
                            self.dlg.textLog.append(self.tr("WARNING: DSM file {} and DTM file {} not found. The related CHM will not be computed.\n").format(sf["N_DSM"], sf["N_DTM"]))
                            QCoreApplication.processEvents()
                    
                    if check_dsm_zip == 1 :
                            for r_dsm_unz in dsm_unzipped:
                                dsm_unz_path = os.path.join(dsm_path, r_dsm_unz)
                                os.remove(dsm_unz_path)
                        
                    if check_dtm_zip == 1:
                        for r_dtm_unz in dtm_unzipped:
                            dtm_unz_path = os.path.join(dtm_path, r_dtm_unz)
                            os.remove(dtm_unz_path)
                
            new_lyr_tile.commitChanges()
            
            if self.aoiIndex != -1 and len(chm_list_merge) > 0:
                clip_pathfile = os.path.join(self.chm_path_folder, '{}{}'.format(self.NameClip, f2))
                self.clip(chm_out_tempdir, selectedAoiFeats, chm_list_merge, f1, f2, clip_pathfile, sf)
                lyr_clip = QgsRasterLayer(clip_pathfile, self.NameClip)
                QgsProject.instance().addMapLayers([lyr_clip], False)
                group_lyr.insertLayer(0, lyr_clip)

            #self.iface.messageBar().pushSuccess("Success", "Selection Done.")
            #print('sono in run e ora chiudo')
            self.mainLog(selectedAoi, selectedCampaign, selectedFormat, sf)
            #print(result)
            
            
