from PyQt5.QtCore import *
from PyQt5.QtGui import *
from qgis.core import *
from qgis.gui import *
from PyQt5.QtWidgets import *
import GdalTools_utils as Utils
try:
    from PyQt5.QtCore import QString
except ImportError:
    QString = str
from processing.core.Processing import Processing
#from processing.core.ProcessingUtils import ProcessingUtils
import ftools_utils
from osgeo import ogr
from processing import *
#from processing.core.QGisLayers import QGisLayers
from processing.core.GeoAlgorithm import GeoAlgorithm
from osgeo.gdalconst import GA_ReadOnly
from osgeo import gdal
from processing import ProcessingPlugin
#from processing.outputs import OutputRaster
import sys, os
import numpy
from .Ui_RUSLE import Ui_RUSLE
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry


class RUSLE(QDialog, Ui_RUSLE):
    
    def __init__(self, iface):
        QDialog.__init__(self)
        self.iface = iface
        self.setupUi(self)  
    
        self.selectButton.clicked.connect(self.fillInputFileEdit)
        self.selectButton2.clicked.connect(self.fillInputFileEdit2)
        self.selectButton3.clicked.connect(self.fillInputFileEdit3)
        self.selectButton4.clicked.connect(self.fillInputFileEdit4)
        self.selectButton5.clicked.connect(self.fillInputFileEdit5)
        self.selectButton_out.clicked.connect(self.fillOutputFileEdit)
        self.buttonBox.accepted.connect(self.convert)
        
        # connect help
        #self.buttonBox.button(QtGui.QDialogButtonBox.Help), SIGNAL("clicked()"), self.help)
              
        
    def help(self):
        QMessageBox.about(self, "RUSLE", """<p><b>RUSLE Index</b></p> 
        <p><b>Definition:</b>The last feature, the RUSLE index, corresponds to the final map, which results from the multiplication of the five factor
        maps created before as defined in equation 1, according to Renard et al. (1997).  </p>
        <p><b>RUSLE</b> = R x K x LS x C x P	(1)</p>
        <p>R is the erosivity factor, calculated over 1 year, a measure of the erosive forces of rainfall-runoff, K is the soil erodibility factor, 
        LS (unitless) is the combination of slope length (L) and slope steepness (S), C (unitless) is the land cover factor, and P is the 
        practices used for erosion control (unitless, ranging between 0 and 1).
        The RUSLE interface is composed by six input files corresponding to R, K, LS, C and P raster files, and an output file corresponding to RUSLE index map. </p>
        <p><b>Method</b></p> 
        <p>Input files = five raster created before. </p>
        <p><b>Output file:</b> RUSLE raster file. </p>""")  
      
 # INPUT RASTER FILE
    def fillInputFileEdit(self):
        lastUsedFilter = Utils.FileFilter.lastUsedRasterFilter()
        inputFile, encoding = Utils.FileDialog.getOpenFileName(self, self.tr( "Select the input file" ), Utils.FileFilter.allRastersFilter(), lastUsedFilter, True)
        self.lastEncoding = encoding
        self.inputLayerCombo.addItem(inputFile)
        check = QFile(inputFile)     
        
    def fillInputFileEdit2(self):
        lastUsedFilter = Utils.FileFilter.lastUsedRasterFilter()
        inputFile, encoding = Utils.FileDialog.getOpenFileName(self, self.tr( "Select the input file" ), Utils.FileFilter.allRastersFilter(), lastUsedFilter, True)
        self.lastEncoding = encoding
        self.inputLayerCombo2.addItem(inputFile)
        check = QFile(inputFile)    
        
    def fillInputFileEdit3(self):
        lastUsedFilter = Utils.FileFilter.lastUsedRasterFilter()
        inputFile, encoding = Utils.FileDialog.getOpenFileName(self, self.tr( "Select the input file" ), Utils.FileFilter.allRastersFilter(), lastUsedFilter, True)
        self.lastEncoding = encoding
        self.inputLayerCombo3.addItem(inputFile)
        check = QFile(inputFile) 
            
    def fillInputFileEdit4(self):
        lastUsedFilter = Utils.FileFilter.lastUsedRasterFilter()
        inputFile, encoding = Utils.FileDialog.getOpenFileName(self, self.tr( "Select the input file" ), Utils.FileFilter.allRastersFilter(), lastUsedFilter, True)
        self.lastEncoding = encoding
        self.inputLayerCombo4.addItem(inputFile)
        check = QFile(inputFile) 
            
    def fillInputFileEdit5(self):
        lastUsedFilter = Utils.FileFilter.lastUsedRasterFilter()
        inputFile, encoding = Utils.FileDialog.getOpenFileName(self, self.tr( "Select the input file" ), Utils.FileFilter.allRastersFilter(), lastUsedFilter, True)
        self.lastEncoding = encoding
        self.inputLayerCombo5.addItem(inputFile)
        check = QFile(inputFile) 
        
# --------------------------------------- // ----------------------------------------------------- // ------------------------------------------------------------------------------

# OUTPUT RASTER FILE
    def fillOutputFileEdit(self):
        lastUsedFilter = Utils.FileFilter.lastUsedRasterFilter()
        outputFile = Utils.FileDialog.getSaveFileName(self, self.tr( "Select the raster file to save the results to" ), Utils.FileFilter.allRastersFilter(), lastUsedFilter )
        if outputFile==None:
            return
        Utils.FileFilter.setLastUsedRasterFilter(lastUsedFilter)
        self.outputFormat = Utils.fillRasterOutputFormat( lastUsedFilter, outputFile )
        self.outputLayerCombo.setText(outputFile) 
    
# RUSLE CALCULATION
    def convert(self):
        self.buttonBox.button(QDialogButtonBox.Ok).setDefault(False)
        # read D raster
        inputLayer = self.inputLayerCombo.currentText()
        #QMessageBox.about(self, "RUSLE", str(inputLayer))
        # read R raster
        inputLayer2 = self.inputLayerCombo2.currentText()
        # read A raster
        inputLayer3 = self.inputLayerCombo3.currentText()
        # read S raster
        inputLayer4 = self.inputLayerCombo4.currentText()
        # read T raster
        inputLayer5 = self.inputLayerCombo5.currentText()
       
        outPath = self.outputLayerCombo.text()  

        gdal.AllRegister()
        
        list_factors = []
        
        # sum of the raster = RUSLE
        # R factor
        #gdalRaster = gdal.Open(str(inputLayer))
        ## multiply by weight
        #R_factor = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/R_factor"
        #x = gdalRaster.RasterXSize
        #y = gdalRaster.RasterYSize
        #geo = gdalRaster.GetGeoTransform()
        #band = gdalRaster.GetRasterBand(1)
        #data = band.ReadAsArray(0,0,x,y)    
        #mul = numpy.multiply(data, int(self.lineWeightD.value()))
        ## Create an output imagedriver with the reclassified values multiplied by the weight
        #driver = gdal.GetDriverByName( "GTiff" ) 
        #outData = driver.Create(str(R_factor), x,y,1, gdal.GDT_Float32)
        #outData.GetRasterBand(1).WriteArray(mul)
        #outData.SetGeoTransform(geo)  
        #outData = None  
        
        #geo = gdalRaster.GetGeoTransform()
        ## pixel size
        #pixelSize = geo[1]
        ## extent
        #minx = geo[0]
        #maxy = geo[3]
        #maxx = minx + geo[1]*x
        #miny = maxy + geo[5]*y
        #extent = str(minx) + "," + str(maxx) + "," + str(miny) + "," + str(maxy)
        #band = gdalRaster.GetRasterBand(1)
        #data_d = band.ReadAsArray(0,0,x,y)
        #QMessageBox.about(self, "RUSLE", str(data_d))
        #depth_weight_dir = depth_weight + "." + "tif"
        
        gdalRaster_d = gdal.Open(str(inputLayer))
        x_d = gdalRaster_d.RasterXSize
        y_d = gdalRaster_d.RasterYSize
        geo_d = gdalRaster_d.GetGeoTransform()
        minx = geo_d[0]
        maxy = geo_d[3]
        maxx = minx + geo_d[1]*x_d
        miny = maxy + geo_d[5]*y_d
        extent = str(minx) + "," + str(maxx) + "," + str(miny) + "," + str(maxy)        
        pixelSize = geo_d[1]
        band_d = gdalRaster_d.GetRasterBand(1)
        data_d = band_d.ReadAsArray(0,0,x_d,y_d)   
        #QMessageBox.about(self, "RUSLE", str(data_d))  
        #QMessageBox.about(self, "RUSLE", str(extent))  
        #QMessageBox.about(self, "RUSLE", str(pixelSize)) 
        
        #list_factors.append(str(inputLayer))
        
        # K
        # resampling K raster
        #gdalRaster2 = gdal.Open(str(inputLayer2))
        # multiply by weight
        #K_factor = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/K_factor"
        #x2 = gdalRaster2.RasterXSize
        #y2 = gdalRaster2.RasterYSize
        #geo2 = gdalRaster2.GetGeoTransform()
        #band2 = gdalRaster2.GetRasterBand(1)
        #data2 = band2.ReadAsArray(0,0,x2,y2)    
        #mul2 = numpy.multiply(data2, int(self.lineWeightR.value()))
        ## Create an output imagedriver with the reclassified values multiplied by the weight
        #driver2 = gdal.GetDriverByName( "GTiff" ) 
        #outData2 = driver2.Create(str(recharge_weight), x2,y2,1, gdal.GDT_Float32)
        #outData2.GetRasterBand(1).WriteArray(mul2)
        #outData2.SetGeoTransform(geo2)  
        #outData2 = None         
        
        Processing.initialize()
        #resamp_k = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/resamp_r" 
        K_factor = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/K_factor_resamp"
        Processing.runAlgorithm("saga:resampling", None, inputLayer2, True, 0, 0, extent, pixelSize, K_factor)   
        resamp_k = K_factor + "." + "tif"
        # K
        gdalRaster_k = gdal.Open(str(resamp_k))
        x_k = gdalRaster_k.RasterXSize
        y_k = gdalRaster_k.RasterYSize
        geo_k = gdalRaster_k.GetGeoTransform()
        band_k = gdalRaster_k.GetRasterBand(1)
        data_k = band_k.ReadAsArray(0,0,x_k,y_k)   
        #QMessageBox.about(self, "RUSLE", str(data_r))
        
        list_factors.append(str(resamp_k))
        
        # LS
        # resampling LS raster
        #gdalRaster3 = gdal.Open(str(inputLayer3))
        # multiply by weight
        LS_factor = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/LS_factor_resamp"
        #x3 = gdalRaster3.RasterXSize
        #y3 = gdalRaster3.RasterYSize
        #geo3 = gdalRaster3.GetGeoTransform()
        #band3 = gdalRaster3.GetRasterBand(1)
        #data3 = band3.ReadAsArray(0,0,x3,y3)    
        #mul3 = numpy.multiply(data3, int(self.lineWeightA.value()))
        ## Create an output imagedriver with the reclassified values multiplied by the weight
        #driver3 = gdal.GetDriverByName( "GTiff" ) 
        #outData3 = driver3.Create(str(aquifer_weight), x3,y3,1, gdal.GDT_Float32)
        #outData3.GetRasterBand(1).WriteArray(mul3)
        #outData3.SetGeoTransform(geo3)  
        #outData3 = None          
        #resamp_ls = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/resamp_ls" 
        Processing.runAlgorithm("saga:resampling", None, inputLayer3, True, 0, 0, extent, pixelSize, LS_factor)   
        resamp_ls = LS_factor + "." + "tif"    
        # LS
        gdalRaster_a = gdal.Open(str(resamp_ls))
        x_a = gdalRaster_a.RasterXSize
        y_a = gdalRaster_a.RasterYSize
        geo_a = gdalRaster_a.GetGeoTransform()
        band_a = gdalRaster_a.GetRasterBand(1)
        data_a = band_a.ReadAsArray(0,0,x_a,y_a)
        #QMessageBox.about(self, "RUSLE", str(data_a))
        
        list_factors.append(str(resamp_ls))
        
        # C
        # resampling C raster
        #gdalRaster4 = gdal.Open(str(inputLayer4))
        # multiply by weight
        C_factor = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/C_factor_resamp"
        #x4 = gdalRaster4.RasterXSize
        #y4 = gdalRaster4.RasterYSize
        #geo4 = gdalRaster4.GetGeoTransform()
        #band4 = gdalRaster4.GetRasterBand(1)
        #data4 = band4.ReadAsArray(0,0,x4,y4)    
        #mul4 = numpy.multiply(data4, int(self.lineWeightS.value()))
        ## Create an output imagedriver with the reclassified values multiplied by the weight
        #driver4 = gdal.GetDriverByName( "GTiff" ) 
        #outData4 = driver4.Create(str(soil_weight), x4,y4,1, gdal.GDT_Float32)
        #outData4.GetRasterBand(1).WriteArray(mul4)
        #outData4.SetGeoTransform(geo4)  
        #outData4 = None   
        
        # find nodata values
        #if self.lineWeightS.value()==2:
            #error = -299997        
        
        #soil_weight_correct = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/soil_weight_correct"
        # reclassify no data values
        #Processing.initialize()
        #Processing.runAlgorithm("saga:reclassifygridvalues", None, soil_weight, 0, error, 0, 0, 0.0, 1.0, 2.0, 0, "0,0,0,0,0,0,0,0,0", 0, True, 0.0, False, 0.0, soil_weight_correct)    
        #soil_weight_fine = soil_weight_correct + "." + "tif"
        
        
        #resamp_s = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/resamp_s" 
        Processing.runAlgorithm("saga:resampling", None, inputLayer4, True, 0, 0, extent, pixelSize, C_factor)   
        resamp_c = C_factor + "." + "tif"
        # C
        gdalRaster_s = gdal.Open(str(resamp_c))
        x_s = gdalRaster_s.RasterXSize
        y_s = gdalRaster_s.RasterYSize
        geo_s = gdalRaster_s.GetGeoTransform()
        band_s = gdalRaster_s.GetRasterBand(1)
        data_s = band_s.ReadAsArray(0,0,x_s,y_s)
        #QMessageBox.about(self, "RUSLE", str(data_s))
        
        list_factors.append(str(resamp_c))
        
        # P
        # resampling P raster
        #gdalRaster5 = gdal.Open(str(inputLayer5))
        # multiply by weight
        P_factor = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/P_factor_resamp"
        #x5 = gdalRaster5.RasterXSize
        #y5 = gdalRaster5.RasterYSize
        #geo5 = gdalRaster5.GetGeoTransform()
        #band5 = gdalRaster5.GetRasterBand(1)
        #data5 = band5.ReadAsArray(0,0,x5,y5)    
        #mul5 = numpy.multiply(data5, int(self.lineWeightT.value()))
        ## Create an output imagedriver with the reclassified values multiplied by the weight
        #driver5 = gdal.GetDriverByName( "GTiff" ) 
        #outData5 = driver5.Create(str(topography_weight), x5,y5,1, gdal.GDT_Float32)
        #outData5.GetRasterBand(1).WriteArray(mul5)
        #outData5.SetGeoTransform(geo5)  
        #outData5 = None        
        #resamp_t = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/resamp_t" 
        Processing.runAlgorithm("saga:resampling", None, inputLayer5, True, 0, 0, extent, pixelSize, P_factor)   
        resamp_p = P_factor + "." + "tif"
        # P
        gdalRaster_t = gdal.Open(str(resamp_p))
        x_t = gdalRaster_t.RasterXSize
        y_t = gdalRaster_t.RasterYSize
        geo_t = gdalRaster_t.GetGeoTransform()
        band_t = gdalRaster_t.GetRasterBand(1)
        data_t = band_t.ReadAsArray(0,0,x_t,y_t)
        #QMessageBox.about(self, "RUSLE", str(data_t))
        
        list_factors.append(str(resamp_p))
        
        Processing.runAlgorithm("saga:rastercalculator", None, inputLayer,list_factors,"a*b*c*d*e", False,8, outPath)
        
        # multiply
        #mul = data_d * data_k * data_a * data_s * data_t
        #QMessageBox.about(self, "RUSLE", str(mul))
        
        #mul_nodata = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/mul_nodata"
        #mul_nodata_rec = mul_nodata + "." + "tif"
        
        # Create an output imagedriver with the reclassified values multiplied by the weight
        #driver_mul = gdal.GetDriverByName( "GTiff" ) 
        #outData_mul = driver_mul.Create(str(outPath), x_d,y_d,1, gdal.GDT_Float32)
        #outData_mul.GetRasterBand(1).WriteArray(mul)
        #outData_mul.SetGeoTransform(geo_d)  
        #outData_mul = None    
        
        #rusle = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/"
        #Processing.runAlgorithm("saga:rastercalculator", None, inputLayer, resamp_k, resamp_ls, resamp_c, resamp_p, "a*b*c*d*e", outPath) 
        #Processing.runAlgorithm("saga:rastercalculator", None, ";".join(list_factors), "a*b*c*d*e", outPath) 
        
        
        ## reclassify no data values
        #Processing.runAlgorithm("saga:reclassifygridvalues", None, sum_nodata, 0, -10000100352, 0, 0, 0.0, 1.0, 2.0, 0, "0,0,0,0,0,0,0,0,0", 0, True, 0.0, False, 0.0, outPath)        
        
        #if self.checkRUSLE.isChecked():
        
        
        # add result into canvas
        file_info = QFileInfo(outPath)
        if file_info.exists():
            layer_name = file_info.baseName()
        else:
            return False
        rlayer_new = QgsRasterLayer(outPath, layer_name)
        if rlayer_new.isValid():
            
            QgsMapLayerRegistry.instance().addMapLayer(rlayer_new)       
            return True
        else:
            return False   
        QMessageBox.information(self, self.tr( "Finished" ), self.tr( "RUSLE completed." ) )                    
    
        #colorfile = 'C:/OSGeo4W64/apps/qgis/python/plugins/RUSLE/colorfile.clr'
        #outPath_color = self.outputLayerCombo_color.text()
        #from colorize import raster2png
              
        #raster2png(outPath, colorfile , outPath_color,1, False)
        
        #if self.checkcolor.isChecked():
            ## add result into canvas
            #file_info = QFileInfo(outPath_color)
            #if file_info.exists():
                #layer_name = file_info.baseName()
            #else:
                #return False
            #rlayer_new = QgsRasterLayer(outPath_color, layer_name)
            #if rlayer_new.isValid():
                #QgsMapLayerRegistry.instance().addMapLayer(rlayer_new)
                #layer = QgsMapCanvasLayer(rlayer_new)
                #layerList = [layer]
                #extent = self.iface.canvas.setExtent(rlayer_new.extent())
                #self.iface.canvas.setLayerSet(layerList)
                #self.iface.canvas.setVisible(True)         
                #return True
            #else:
                #return False    
            #QMessageBox.information(self, self.tr( "Finished" ), self.tr( "RUSLE completed." ) )   
        
        #self.buttonBox.button(QDialogButtonBox.Ok).setDefault(True) 