# -*- coding: utf-8 -*-
"""
/***************************************************************************
 Hand Plugin
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2025-09-19
        git sha              : $Format:%H$
        copyright            : (C) 2025 by João Vitor Lima & Adriano Paz
        email                : jvdsl_off@outlook.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 html
from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon, QFont, QDoubleValidator
from qgis.PyQt.QtWidgets import QApplication, QAction, QFileDialog, QMessageBox
from qgis.core import QgsMapLayerProxyModel, Qgis, QgsProject, QgsRasterLayer, QgsMapLayer
import qgis.utils

# Initialize Qt resources from file resources.py
from .resources_rc import *
# Import the code for the dialog
from .hand_module_dialog import HandDialog
import os.path
from pathlib import Path
from osgeo import ogr, gdal, gdalconst
import subprocess
from datetime import datetime
import platform
import numpy as np


class Hand:
    """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')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'Hand_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&HAND Plugin')

        # 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.dlg_hand = HandDialog()
        self.current_dir = os.path.dirname(os.path.abspath(__file__))
        self.projection = 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('Hand', 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 traduz_interface(self, idioma: str):
        """Traduz os textos da interface e mensagens para o idioma selecionado ('pt' ou 'en')."""
        self.current_lang = idioma
        # Mensagens traduzidas
        self.msgs = {
            'pt': {
                'no_file_selected': 'Nenhum arquivo foi selecionado.',
                'warning_title': 'Atenção',
                'error_title': 'Erro!',
                'info_title': 'Informação!',
                'invalid_filename': 'Por favor, forneça um nome de arquivo válido para salvar o HAND.',
                'invalid_filename2': 'Por favor, forneça um nome de arquivo válido para salvar o mapa de áreas suscetíveis a inundação.',
                'invalid_path': 'Por favor, forneca um caminho válido para salvar o HAND.',
                'success': 'Operação realizada com sucesso!',
                'hand_success': 'HAND determinado com sucesso...',
                'hand_start': 'Iniciando processamento do HAND...',
                'hand_convert': 'Convertendo arquivo para GeoTIFF...',
                'hand_add': 'Adicionando arquivo ao QGIS...',
                'hand_error': 'Por favor, verifique se os arquivos enviados correspondem aos que foram solicitados.',
                'cancel_log': '<font>\nATENÇÃO: interrompendo o processo HAND...</font>',
                'success_log': 'Êxito! Operação realizada com sucesso...',
                'invalid_threshold': 'Por favor, forneça um valor válido para o limiar.'
            },
            'en': {
                'no_file_selected': 'No file was selected.',
                'warning_title': 'Warning',
                'error_title': 'Error!',
                'info_title': 'Information!',
                'invalid_filename': 'Please provide a valid file name to save HAND.',
                'invalid_filename2': 'Please provide a valid file name to save the flood-prone area map.',
                'invalid_path': 'Please provide a valid path to save HAND.',
                'success': 'Operation completed successfully!',
                'hand_success': 'HAND successfully determined...',
                'hand_start': 'Starting HAND processing...',
                'hand_convert': 'Converting file to GeoTIFF...',
                'hand_add': 'Adding file to QGIS...',
                'hand_error': 'Please check if the provided files match the requested ones.',
                'cancel_log': '<font>\nATTENTION: stopping HAND process...</font>',
                'success_log': 'Success! Operation completed successfully...',
                'invalid_threshold': 'Please provide a valid value for the threshold.'
            }
        }
        # ...interface translation as before...
        """Traduz os textos da interface para o idioma selecionado ('pt' ou 'en')."""
        if idioma == 'pt':
            html_description = (
                '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">'
                '<html><head><meta name="qrichtext" content="1" /><style type="text/css">'
                'p, li { white-space: pre-wrap; }'
                '</style></head><body style=" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal;">'
                '<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; color:#7c7c7c;">Descrição<br /></span></p>'
                '<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; color:#838383;">Este plugin determina o Height Above Nearest Drainage (HAND), um descritor de terreno definido pela diferença de elevação entre um ponto de superfície e o ponto mais próximo da rede de drenagem para o qual ele drena¹. O plugin também gera o mapa de inundação para um limiar informado.</span></p>'
                '<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; color:#838383;"><br /></p>'
                '<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; color:#838383;"><br /></p>'
                '<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; color:#838383;">¹RENNÓ, C.D.</span><span style=" font-size:7pt; font-style:italic; color:#838383;"> et a</span><span style=" font-size:7pt; color:#838383;">l. “HAND, a new terrain descriptor using SRTM-DEM: mapping terra-firmerainforest environments in Amazonia”. Remote Sensing of Environment 112, 3469-3481, 2008.</span></p></body></html>'
            )
            self.dlg_hand.textEdit.setHtml(html_description)

            self.dlg_hand.setWindowTitle('HAND Plugin')
            self.dlg_hand.tabWidget.setTabText(0, 'Parâmetros')
            self.dlg_hand.tabWidget.setTabText(1, 'Log')
            self.dlg_hand.label.setText('Bacia Hidrográfica')
            self.dlg_hand.label_2.setText('Modelo Digital de Elevação (MDE)')
            self.dlg_hand.label_3.setText('Direções de Fluxo')
            self.dlg_hand.label_5.setText('Rede de Drenagem')
            self.dlg_hand.label_4.setText(
                'Height Above Nearest Drainage (HAND)')
            self.dlg_hand.label_7.setText('Limiar de inundação (m):')
            self.dlg_hand.label_8.setText(
                'Mapa de áraeas suscetíveis a inundação:')
            self.dlg_hand.groupBox.setTitle('Saídas')
            self.dlg_hand.btn_hand.setText('GERAR HAND')
            self.dlg_hand.btn_cancel.setText('FECHAR')
            self.dlg_hand.label_6.setText('Selecione o idioma:')
            self.dlg_hand.label_11.setToolTip(
                'Adicione a delimitação da bacia hidrográfica. O arquivo deve ser raster (GeoTIFF).')
            self.dlg_hand.label_12.setToolTip(
                'Adicione o modelo digital de elevação. O arquivo deve ser raster (GeoTIFF).')
            self.dlg_hand.label_13.setToolTip(
                'Adicione a direção de fluxo. O arquivo deve ser raster (GeoTIFF).')
            self.dlg_hand.label_14.setToolTip(
                'Adicione a rede de drenagem. O arquivo deve ser raster (GeoTIFF).')
            self.dlg_hand.label_15.setToolTip(
                'Selecione uma pasta para salvar o HAND resultante (.tif). O arquivo será adicionado ao projeto QGIS atual!')

            html_tooltip = """
                <html>
                <head/>
                    <body>
                        <p>
                            Define o limiar de elevação (m) para identificação de áreas inundadas. 
                            Células com valores de HAND abaixo desse limiar são classificadas como inundadas.
                        </p>
                    </body>
                </html>"""

            self.dlg_hand.label_16.setToolTip(html_tooltip)
            self.dlg_hand.label_17.setToolTip(
                'Selecione uma pasta para salvar o mapa de áreas suscetíveis a inundação (.tif). O arquivo será adicionado ao projeto QGIS atual!')

        else:
            html_description = (
                '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">'
                '<html><head><meta name="qrichtext" content="1" /><style type="text/css">'
                'p, li { white-space: pre-wrap; }'
                '</style></head><body style=" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal;">'
                '<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; color:#7c7c7c;">Description<br /></span></p>'
                '<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; color:#838383;">This plugin determines the Height Above Nearest Drainage (HAND), a terrain descriptor defined as the elevation difference between a surface point and the nearest drainage network point to which it drains¹. It also generates a flood map for a given threshold.</span></p>'
                '<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; color:#838383;"><br /></p>'
                '<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; color:#838383;"><br /></p>'
                '<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; color:#838383;">¹RENNÓ, C.D.</span><span style=" font-size:7pt; font-style:italic; color:#838383;"> et a</span><span style=" font-size:7pt; color:#838383;">l. “HAND, a new terrain descriptor using SRTM-DEM: mapping terra-firmerainforest environments in Amazonia”. Remote Sensing of Environment 112, 3469-3481, 2008.</span></p></body></html>'
            )
            self.dlg_hand.textEdit.setHtml(html_description)

            self.dlg_hand.setWindowTitle('HAND Plugin')
            self.dlg_hand.tabWidget.setTabText(0, 'Parameters')
            self.dlg_hand.tabWidget.setTabText(1, 'Log')
            self.dlg_hand.label.setText('Watershed delineation')
            self.dlg_hand.label_2.setText('Digital Elevation Model (DEM)')
            self.dlg_hand.label_3.setText('Flow Directions')
            self.dlg_hand.label_5.setText('River Drainage Network')
            self.dlg_hand.label_4.setText(
                'Height Above Nearest Drainage (HAND)')
            self.dlg_hand.label_7.setText('Flood map threshold (m):')
            self.dlg_hand.label_8.setText('Flood-prone area map:')
            self.dlg_hand.groupBox.setTitle('Outputs')
            self.dlg_hand.btn_hand.setText('RUN HAND')
            self.dlg_hand.btn_cancel.setText('CLOSE')
            self.dlg_hand.label_6.setText('Select language:')
            self.dlg_hand.label_11.setToolTip(
                'Add the watershed delineation. The file must be a raster type (GeoTIFF).')
            self.dlg_hand.label_12.setToolTip(
                'Add the digital elevation model. The file must be a raster type (GeoTIFF).')
            self.dlg_hand.label_13.setToolTip(
                'Add the flow direction. The file must be a raster type (GeoTIFF).')
            self.dlg_hand.label_14.setToolTip(
                'Add the River Drainage Network. The file must be a raster type (GeoTIFF).')

            self.dlg_hand.label_15.setToolTip(
                'Select a folder to save the resulting HAND (.tif). The file will be added to the current QGIS project!')

            html_tooltip = """
            <html>
            <head/>
            <body>
            <p>
                Defines the elevation threshold (in meters) used to classify flooded areas based on HAND values. 
                Pixels with HAND values below this threshold are considered flooded.
            </p>
            </body>
            </html>
            """
            self.dlg_hand.label_16.setToolTip(html_tooltip)
            self.dlg_hand.label_17.setToolTip(
                "Select a folder to save the flood-prone area map (.tif). The file will be added to the current QGIS project!")

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        icon_path = os.path.join(self.current_dir, 'icon.png')
        self.add_action(
            icon_path,
            text=self.tr(u'HAND Plugin'),
            callback=self.run,
            parent=self.iface.mainWindow())

        # will be set False in run()
        self.first_start = True

        # Aplica filtro para apenas raster aos comboboxes
        self.dlg_hand.cb_01.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.dlg_hand.cb_02.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.dlg_hand.cb_03.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.dlg_hand.cb_04.setFilters(QgsMapLayerProxyModel.RasterLayer)

        # Aplica filtro de valores float maiores que zero no le_02
        validator = QDoubleValidator(0.0, 999999.99, 2)
        validator.setBottom(0.01)  # Garante que o valor seja maior que zero
        self.dlg_hand.le_02.setValidator(validator)

        # Configura selecoes de arquivos
        self.dlg_hand.btn_01.clicked.connect(
            lambda: self.carregaArquivos(self.dlg_hand.cb_01))
        self.dlg_hand.btn_02.clicked.connect(
            lambda: self.carregaArquivos(self.dlg_hand.cb_02))
        self.dlg_hand.btn_03.clicked.connect(
            lambda: self.carregaArquivos(self.dlg_hand.cb_03))
        self.dlg_hand.btn_04.clicked.connect(
            lambda: self.carregaArquivos(self.dlg_hand.cb_04))
        self.dlg_hand.btn_05.clicked.connect(
            lambda: self.save_buttons(self.dlg_hand.le_01))
        self.dlg_hand.btn_06.clicked.connect(
            lambda: self.save_buttons(self.dlg_hand.le_03))

        # Inicia processamento
        self.dlg_hand.btn_hand.clicked.connect(lambda: self.run_process_hand())
        self.dlg_hand.btn_cancel.clicked.connect(
            lambda: self.cancel_log_page())

        # Conecta os botões de idioma
        self.dlg_hand.btn_eng.clicked.connect(
            lambda: self.traduz_interface('en'))
        self.dlg_hand.btn_ptbr.clicked.connect(
            lambda: self.traduz_interface('pt'))

        # Inicializa interface em inglês
        self.traduz_interface('en')

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(
                self.tr(u'&HAND Plugin'),
                action)
            self.iface.removeToolBarIcon(action)

    def del_temp_files(self):
        """This function deletes the temporary files created during the plugin execution."""
        temp_path = Path(self.current_dir + r'\temp')

        # Select all files except the executable
        arquivos = [f for f in temp_path.iterdir() if f.is_file()
                    and f.suffix.lower() != ".exe"]

        # Delete all files
        for file in arquivos:
            os.remove(file)

    def carregaArquivos(self, combobox, file_type="raster"):
        """This function is used to add the files sent by the user to the plugin."""
        # Define the variables and settings of the file selection window
        file_ = None
        options = QFileDialog.Options()

        while True:  # Loop until the user selects a file or cancels

            # Dialog window with the User
            if file_type == "raster":
                file_, _ = QFileDialog.getOpenFileName(
                    None, "Select a file!", "", "GeoTIFF (*.tif)", options=options)
                if not file_:
                    result = self.msgs[self.current_lang]['no_file_selected']
                    reply = QMessageBox.warning(
                        self.dlg_hand, self.msgs[self.current_lang]['warning_title'], result, QMessageBox.Ok)
                    if reply == QMessageBox.Ok:
                        break

                # If the raster is not in the project, add it
                if file_ not in [layer.source() for layer in QgsProject.instance().mapLayers().values()]:
                    layer = QgsRasterLayer(
                        file_, os.path.basename(file_), "gdal")
                    QgsProject.instance().addMapLayer(layer)

                # Add the file to the combo box
                combobox.setLayer(layer)

                return file_

    def save_buttons(self, line_edit):
        '''This function configures the save buttons (create file).'''
        # Select the file sent by the user
        while True:
            file_name, _ = QFileDialog.getSaveFileName(
                None, "Save the file.", '', "GeoTIFF(*.tif)")
            if file_name:
                line_edit.setText(file_name)
                break

            else:
                # The user did not select a file (a path to save the output file)
                result = self.msgs[self.current_lang]['no_file_selected']
                reply = QMessageBox.warning(
                    self.dlg_hand, self.msgs[self.current_lang]['warning_title'], result, QMessageBox.Ok)
                if reply == QMessageBox.Ok:
                    break

    def cancel_log_page(self):
        '''This function configures the cancel button of the log page.'''
        self.dlg_hand.te_logg.clear()
        mensagem_log1 = self.msgs[self.current_lang]['cancel_log']
        self.dlg_hand.te_logg.insertHtml(mensagem_log1)

        # Clear line edits
        self.dlg_hand.le_01.clear()
        self.dlg_hand.le_02.clear()
        self.dlg_hand.le_03.clear()

        # Reactivate the parameters page
        self.dlg_hand.pg_parameters.setEnabled(True)

        # Deactivate the log page
        self.dlg_hand.pg_log_hand.setEnabled(False)

        # Delete created files
        self.del_temp_files()

        # Reset progressBar
        self.dlg_hand.progressBar.setValue(0)

        # Clear log page
        self.dlg_hand.te_logg.clear()

        # Close the gui
        self.dlg_hand.close()

    def le_geotiff_escreve_bin(self):
        """This function reads the .tif file sent by the user and converts it to binary .rst type for reading in fortran."""
        # Clear temp folder
        self.del_temp_files()

        # Define the paths for the temporary GeoTIFF files
        basin_temp_tif = self.current_dir + r'\temp\bacia_temp.tif'
        DEM_temp_tif = self.current_dir + r'\temp\MDE_temp.tif'
        dir_temp_tif = self.current_dir + r'\temp\dir_temp.tif'
        drainage_temp_tif = self.current_dir + r'\temp\drenagem_temp.tif'

        self.dlg_hand.progressBar.setValue(5)
        # Convert the input files to the correct data types in temporary copies
        gdal.Translate(basin_temp_tif, self.dlg_hand.cb_01.currentLayer(
        ).source(), outputType=gdal.GDT_Int16)

        # store geotransform and projection
        dataset = gdal.Open(self.dlg_hand.cb_01.currentLayer().source())
        self.projection = dataset.GetProjection()
        dataset = None  # Close the dataset

        self.dlg_hand.progressBar.setValue(10)
        gdal.Translate(DEM_temp_tif, self.dlg_hand.cb_02.currentLayer(
        ).source(), outputType=gdal.GDT_Float32)
        self.dlg_hand.progressBar.setValue(15)
        gdal.Translate(dir_temp_tif, self.dlg_hand.cb_03.currentLayer(
        ).source(), outputType=gdal.GDT_Int16)
        self.dlg_hand.progressBar.setValue(20)
        gdal.Translate(drainage_temp_tif, self.dlg_hand.cb_04.currentLayer(
        ).source(), outputType=gdal.GDT_Int16)
        self.dlg_hand.progressBar.setValue(25)

        # Binary rst files
        basin_rst = self.current_dir + r'\temp\bacia.rst'
        DEM_rst = self.current_dir + r'\temp\MDE.rst'
        dir_rst = self.current_dir + r'\temp\dir.rst'
        drainage_rst = self.current_dir + r'\temp\drenagem.rst'

        # Convert the temporary copies to RST format
        gdal.Translate(basin_rst, basin_temp_tif, format="RST")
        self.dlg_hand.progressBar.setValue(30)

        # Convert DEM
        gdal.Translate(DEM_rst, DEM_temp_tif, format="RST")
        self.dlg_hand.progressBar.setValue(35)

        # Convert flow directions
        gdal.Translate(dir_rst, dir_temp_tif, format="RST")
        self.dlg_hand.progressBar.setValue(40)

        # Convert drainage network
        gdal.Translate(drainage_rst, drainage_temp_tif, format="RST")
        self.dlg_hand.progressBar.setValue(50)

    def verify_file_name_parameters(self):
        """Checks if the output file name is valid."""
        file_name1 = self.dlg_hand.le_01.text()
        file_name2 = self.dlg_hand.le_03.text()
        threshold = self.dlg_hand.le_02.text()

        if not file_name1.lower().endswith('.tif'):
            QMessageBox.warning(
                self.dlg_hand, self.msgs[self.current_lang]['error_title'], self.msgs[self.current_lang]['invalid_filename'])
            self.dlg_hand.progressBar.setValue(0)
            return False

        if not file_name2.lower().endswith('.tif'):
            QMessageBox.warning(
                self.dlg_hand, self.msgs[self.current_lang]['error_title'], self.msgs[self.current_lang]['invalid_filename2'])
            self.dlg_hand.progressBar.setValue(0)
            return False

        if threshold == '':
            QMessageBox.warning(
                self.dlg_hand, self.msgs[self.current_lang]['error_title'], self.msgs[self.current_lang]['invalid_threshold'])
            self.dlg_hand.progressBar.setValue(0)
            return False

        return True

    def convert_nodata_raster(self):
        """
        Modifies the generated HAND file by assigning NoData to pixels outside the watershed region.
        """
        # Open the HAND raster generated in fortran and converted to tif
        raster = gdal.Open(self.dlg_hand.le_01.text(), gdal.GA_Update)
        bacia = gdal.Open(self.dlg_hand.cb_01.currentLayer().source())
        bacia_raster = bacia.GetRasterBand(1).ReadAsArray()

        # Read the array
        banda = raster.GetRasterBand(1)
        dados = banda.ReadAsArray()

        # Pixels not in basin receive NoData (-9999)
        dados[bacia_raster == 0] = -9999

        # Write back to the band
        banda.WriteArray(dados)

        # Define NoData value (optional but recommended)
        banda.SetNoDataValue(-9999)

        # Save file
        banda.FlushCache()
        raster.FlushCache()
        del raster
        del bacia

    def prone_areas_map(self, hand_raster_path, threshold, output_path):
        """Generates the flood-prone areas map based on the HAND raster and the given threshold."""
        # Open the HAND raster
        hand_raster = gdal.Open(hand_raster_path)
        hand_band = hand_raster.GetRasterBand(1)
        hand_data = hand_band.ReadAsArray()
        bacia = gdal.Open(self.dlg_hand.cb_01.currentLayer().source())
        bacia_raster = bacia.GetRasterBand(1).ReadAsArray()

        # Create a new raster for the flood-prone areas map
        driver = gdal.GetDriverByName('GTiff')
        flood_prone_raster = driver.Create(
            output_path, hand_raster.RasterXSize, hand_raster.RasterYSize, 1, gdal.GDT_Byte)
        flood_prone_raster.SetGeoTransform(hand_raster.GetGeoTransform())
        flood_prone_raster.SetProjection(hand_raster.GetProjection())
        flood_prone_band = flood_prone_raster.GetRasterBand(1)

        # Classify areas as flood-prone (1) or not (0) based on the threshold
        hand_data[hand_data < threshold] = 1
        hand_data[hand_data > threshold] = -9999

        # Define pixels outside the basin as NoData
        hand_data[bacia_raster == 0] = -9999

        # Write the data to the new raster
        flood_prone_band.WriteArray(hand_data)

        # Define -9999 as NoData for non-prone areas
        flood_prone_band.SetNoDataValue(0)

        # Save the file
        flood_prone_band.FlushCache()
        del flood_prone_raster
        del hand_raster

    def run_process_hand(self):
        """Organizes the creation of files that will be read by the Hand routine in fortran.
        Saves and adds the generated raster to the current qgis project."""
        if not self.verify_file_name_parameters():
            return  # If the file name is not valid, interrupt the process

        # Activate the log page and clear the information passed in text_edit
        mensagem_log1 = None
        mensagem_log = None
        self.dlg_hand.tabWidget.setCurrentIndex(1)
        self.dlg_hand.pg_log_hand.setEnabled(True)
        self.dlg_hand.te_logg.clear()
        # Configure the information of the textEdit of the referred page
        font = QFont()
        font.setPointSize(11)
        version_info = {
            "QGIS Version": '3.28.0-Firenze',
            "Qt Version": '5.15.3',
            "Python Version": '3.9.5',
            "GDAL Version": '3.8.0'}

        datatime_started = datetime.now().isoformat()
        mensagem_log1 = "The plugin was developed with:\n"
        mensagem_log1 += f"QGIS Version: {version_info['QGIS Version']}\n"
        mensagem_log1 += f"Qt Version: {version_info['Qt Version']}\n"
        mensagem_log1 += f"Python Version: {version_info['Python Version']}\n"
        mensagem_log1 += f"GDAL Version: {version_info['GDAL Version']}\n"
        mensagem_log1 += "--------------------------------------------------------\n"
        mensagem_log1 += f"Algorithm started at: {datatime_started}\n"
        mensagem_log1 += "--------------------------------------------------------\n"
        if self.current_lang == 'pt':
            mensagem_log1 = "O plugin foi desenvolvido com:\n"
            mensagem_log1 += f"QGIS Versão: {version_info['QGIS Version']}\n"
            mensagem_log1 += f"Qt Versão: {version_info['Qt Version']}\n"
            mensagem_log1 += f"Python Versão: {version_info['Python Version']}\n"
            mensagem_log1 += f"GDAL Versão: {version_info['GDAL Version']}\n"
            mensagem_log1 += "--------------------------------------------------------\n"
            mensagem_log1 += f"Algoritmo iniciado em: {datatime_started}\n"
            mensagem_log1 += "--------------------------------------------------------\n"
        self.dlg_hand.te_logg.append(mensagem_log1)

        # Call function that converts the files
        self.le_geotiff_escreve_bin()

        # Call fortran executable to start hand processing
        mensagem_log = self.msgs[self.current_lang]['hand_start']
        self.dlg_hand.te_logg.append(mensagem_log)
        workdir = self.current_dir + r'\temp'
        if platform.system() == "Windows":
            hand_fortran = os.path.join(
                self.current_dir, "temp", "HAND.exe")
        else:
            hand_fortran = os.path.join(self.current_dir, "temp", "HAND")
            subprocess.run(["chmod", "+x", hand_fortran], cwd=workdir)

        hand_exe = subprocess.run([hand_fortran], cwd=workdir)

        # check if there was any error in the fortran routine processing
        # If not, execution continues in python
        if hand_exe.returncode == 0:
            mensagem_log = self.msgs[self.current_lang]['hand_success']
            self.dlg_hand.te_logg.append(mensagem_log)
            self.dlg_hand.progressBar.setValue(75)

            hand_out = self.current_dir + r'\temp\HAND.rst'

            # Convert hand file to geotiff and add to QGIS
            if os.path.isfile(hand_out) == True and self.dlg_hand.le_01.text() is not '':
                mensagem_log = self.msgs[self.current_lang]['hand_convert']
                self.dlg_hand.te_logg.append(mensagem_log)
                gdal.Translate(self.dlg_hand.le_01.text(),
                               hand_out, format="GTiff", outputType=gdal.GDT_Float32, outputSRS=self.projection)
                self.dlg_hand.progressBar.setValue(90)

                # Save flood-prone area map
                self.prone_areas_map(self.dlg_hand.le_01.text(),
                                     float(self.dlg_hand.le_02.text()), self.dlg_hand.le_03.text())

                # Modify the generated HAND file by assigning 'no data' value to region outside the basin
                self.convert_nodata_raster()

                # Add the result to qgis
                hand_fn = self.dlg_hand.le_01.text()
                flood_map_fn = self.dlg_hand.le_03.text()

                mensagem_log = self.msgs[self.current_lang]['hand_add']
                self.dlg_hand.te_logg.append(mensagem_log)

                hand_layer = QgsRasterLayer(
                    hand_fn, os.path.basename(hand_fn), "gdal")
                flood_map_layer = QgsRasterLayer(
                    flood_map_fn, os.path.basename(flood_map_fn), "gdal")

                QgsProject.instance().addMapLayer(hand_layer)
                QgsProject.instance().addMapLayer(flood_map_layer)

                self.dlg_hand.progressBar.setValue(100)
                mensagem_log = self.msgs[self.current_lang]['success_log']
                self.dlg_hand.te_logg.append(mensagem_log)

                QMessageBox.information(
                    self.dlg_hand, self.msgs[self.current_lang]['info_title'], self.msgs[self.current_lang]['success'])

                self.del_temp_files()

            else:
                QMessageBox.warning(
                    self.dlg_hand, self.msgs[self.current_lang]['error_title'], self.msgs[self.current_lang]['invalid_path'])
                self.dlg_hand.progressBar.setValue(0)
                self.del_temp_files()
        else:
            QMessageBox.warning(
                self.dlg_hand, self.msgs[self.current_lang]['error_title'], self.msgs[self.current_lang]['hand_error'])
            self.dlg_hand.progressBar.setValue(0)

    def run(self):
        """Run method that performs all the real work"""
        if not self.dlg_hand.isVisible():
            # Se o diálogo não estiver visível, mostre-o.
            self.dlg_hand.show()
        else:
            # Se já estiver visível, traga-o para a frente e dê o foco.
            self.dlg_hand.raise_()
            self.dlg_hand.activateWindow()
