from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.core import *
from qgis.gui import *
from qgis.PyQt.QtWidgets import *
from . import GdalTools_utils

try:
    from qgis.PyQt.QtCore import QString
except ImportError:
    QString = str
from processing.core.Processing import Processing
# from processing.core.ProcessingGdalTools_utils import ProcessingGdalTools_utils
from . import ftools_utils
from osgeo import ogr
from processing import *
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_ClassWindow import Ui_ClassWindow
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
from qgis.PyQt import QtCore, QtGui
from .downloadWindow import downloadWindow
from . import GdalTools_utils as Utils
from . import ftools_utils

class ClassWindow(QDialog, Ui_ClassWindow):

    def __init__(self, iface):
        QDialog.__init__(self)
        self.iface = iface
        self.setupUi(self)

        self.selectButton.clicked.connect(self.downloadWindow)
        self.selectButton_input.clicked.connect(self.inputFolder)
        self.buttonBox.accepted.connect(self.ok)
        self.selectButton_out.clicked.connect(self.fillInputFileEdit)
        self.outputLayerCombo.currentIndexChanged.connect(self.fillInputAttrib1)


# download window
    def downloadWindow(self):
        self.dlgwindow = downloadWindow(self)
        if downloadWindow ==0:
            return
        self.dlgwindow.show()
        QMessageBox.information(self, self.tr("Sentinel"), self.tr("If you have not sentinelsat installed in your QGIS, please click on button 'Install sentinel'"))

# open input training shapefile
    def fillInputFileEdit(self):
        lastUsedFilter = Utils.FileFilter.lastUsedVectorFilter()
        inputFile, encoding = Utils.FileDialog.getOpenFileName(self, self.tr("Select the input file"),
                                                               Utils.FileFilter.allVectorsFilter(), lastUsedFilter,
                                                               True)
        self.lastEncoding = encoding
        self.loadFields1(inputFile)
        self.outputLayerCombo.addItem(inputFile)
        check = QFile(inputFile)

    def fillInputAttrib1(self, inputFile):
        self.layer = QgsVectorLayer(self.outputLayerCombo.currentText(), (QFileInfo(str(self.outputLayerCombo.currentText()))).baseName()  , "ogr")
        self.comboboxclasse.clear()
        changedField = ftools_utils.getFieldList(self.layer)
        for f in changedField:
            if f.type() == QVariant.String:
                self.comboboxclasse.addItem(str(f.name()))

    def loadFields1(self, vectorFile=QString()):
        if vectorFile == None:
            return
        try:
            (fields, names) = Utils.getVectorFields(vectorFile)
        except Exception as e:
            QErrorMessage(self).showMessage(str(e))
        self.outputLayerCombo.clearEditText()
        ncodec = QTextCodec.codecForName(self.lastEncoding)

    def inputFolder(self):
        settings = QSettings()
        lastDir = settings.value("/fTools/lastRasterDir", ".")
        inDir = QFileDialog.getExistingDirectory(self, self.tr("Select directory with Sentinel images"),
                                                 lastDir)

        if not inDir:
            return

        self.workDir = QDir(inDir)
        self.workDir.setFilter(QDir.Files)
        self.inputFiles = self.workDir.entryList()
        if len(self.inputFiles) == 0:
            QMessageBox.warning(self, self.tr("No files found"),
                                self.tr("There are no files in this directory. Please select another one."))
            self.inputFiles = None
            return

        settings.setValue("/fTools/lastRasterDir", inDir)

        self.comboboxsuperinput.addItem(inDir)


        # perform the classification
    def ok(self):

        #inputImage = self.
        inputTraining = self.outputLayerCombo.currentText()
        training_class = self.comboboxclasse.currentText()

        images = self.comboboxsuperinput.currentText()


        #for filename in os.listdir(images):
            #QMessageBox.about(self, "RUSLE", str(filename))

        Processing.initialize()

        # composite with 6 bands
        my_result = Processing.runAlgorithm("gdal:buildvirtualraster", {
            'INPUT': ['C:/Artigos/SPIE_2019/NovaZonaEstudo/CLIP_images_12/clip_RT_T29TNE_20171012T112111_B08.tif',
                      'C:/Artigos/SPIE_2019/NovaZonaEstudo/CLIP_images_12/clip_RT_T29TNE_20171012T112111_B02.tif',
                      'C:/Artigos/SPIE_2019/NovaZonaEstudo/CLIP_images_12/clip_RT_T29TNE_20171012T112111_B03.tif',
                      'C:/Artigos/SPIE_2019/NovaZonaEstudo/CLIP_images_12/clip_RT_T29TNE_20171012T112111_B04.tif',
                      'C:/Artigos/SPIE_2019/NovaZonaEstudo/CLIP_images_12/clip_RT_T29TNE_20171012T112111_B11.tif',
                      'C:/Artigos/SPIE_2019/NovaZonaEstudo/CLIP_images_12/clip_RT_T29TNE_20171012T112111_B12.tif'],
            'RESOLUTION': 0, 'SEPARATE': True, 'PROJ_DIFFERENCE': False, 'ADD_ALPHA': False, 'ASSIGN_CRS': None,
            'RESAMPLING': 0, 'SRC_NODATA': '', 'OUTPUT': 'TEMPORARY_OUTPUT'})

        composite = my_result['OUTPUT']
        #QMessageBox.about(self, "RUSLE", str(composite))

        if self.comboboxsuper.currentText()=='Supervised':
            if self.methodLayerCombo.currentText()=='SVM':
                # check_output will run the command and store to result
                #x = subprocess.call(cmd, shell=True)
                svm_class = Processing.runAlgorithm("saga:svmclassification", {'GRIDS': [composite],
                            'CLASSES': 'TEMPORARY_OUTPUT',
                            'SCALING': 2, 'MESSAGE': False, 'MODEL_SRC': 0, 'MODEL_LOAD': '',
                            'ROI': inputTraining,
                            'ROI_ID': training_class, 'MODEL_SAVE': '', 'SVM_TYPE': 0, 'KERNEL_TYPE': 2, 'DEGREE': 3,
                            'GAMMA': 0, 'COEF0': 0, 'COST': 1, 'NU': 0.5, 'EPS_SVR': 0.1, 'CACHE_SIZE': 100,
                            'EPS': 0.001, 'SHRINKING': False, 'PROBABILITY': False, 'CROSSVAL': 1})

                svm_class_result = svm_class['CLASSES']

                # layer information
                gdalRaster = gdal.Open(str(svm_class_result))
                x = gdalRaster.RasterXSize
                y = gdalRaster.RasterYSize
                geo = gdalRaster.GetGeoTransform()
                minx = geo[0]
                maxy = geo[3]
                maxx = minx + geo[1] * x
                miny = maxy + geo[5] * y
                extent_raster = str(minx) + "," + str(maxx) + "," + str(miny) + "," + str(maxy)
                pixelSize = geo[1]

                #rasterize training areas
                # rasterize_train = Processing.runAlgorithm("gdal:rasterize",
                #                {'INPUT': inputTraining,
                #                 'FIELD': training_class, 'BURN': 0, 'UNITS': 0, 'WIDTH': pixelSize, 'HEIGHT': pixelSize,
                #                 'EXTENT': extent_raster,
                #                 'NODATA': 0, 'OPTIONS': '', 'DATA_TYPE': 5, 'INIT': None, 'INVERT': False,
                #                 'OUTPUT': 'TEMPORARY_OUTPUT'})

                # rasterize_train = Processing.runAlgorithm("grass7:v.to.rast",
                #                {'input': inputTraining,
                #                 'type': [0, 1, 3], 'where': '', 'use': 0, 'attribute_column': training_class,
                #                 'rgb_column': None, 'label_column': None, 'value': 1, 'memory': 300,
                #                 'output': 'TEMPORARY_OUTPUT', 'GRASS_REGION_PARAMETER': None,
                #                 'GRASS_REGION_CELLSIZE_PARAMETER': 0, 'GRASS_RASTER_FORMAT_OPT': '',
                #                 'GRASS_RASTER_FORMAT_META': '', 'GRASS_SNAP_TOLERANCE_PARAMETER': -1,
                #                 'GRASS_MIN_AREA_PARAMETER': 0.0001})

                rasterize_train = Processing.runAlgorithm("saga:rasterize",
                               {'INPUT': inputTraining,
                                'FIELD': training_class, 'OUTPUT': 2, 'MULTIPLE': 4, 'LINE_TYPE': 0, 'POLY_TYPE': 0,
                                'GRID_TYPE': 3,
                                'TARGET_USER_XMIN TARGET_USER_XMAX TARGET_USER_YMIN TARGET_USER_YMAX': None,
                                'TARGET_USER_SIZE': 100, 'TARGET_USER_FITS': 0, 'GRID': 'TEMPORARY_OUTPUT'})

                train_raster = rasterize_train['GRID']

                #estimate the overall accuracy and kappa values
                Processing.runAlgorithm("grass7:r.kappa", {
                    'classification': svm_class_result,
                    'reference': train_raster,
                    'title': 'ACCURACY ASSESSMENT', '-h': False, '-w': False,
                    'output': str(images)+'/teste.txt',
                    'GRASS_REGION_PARAMETER': None, 'GRASS_REGION_CELLSIZE_PARAMETER': 0})

                lulc_vect = QFileInfo(QgsApplication.qgisUserDatabaseFilePath()).path() + "/lulc_vect"

                Processing.runAlgorithm("saga:vectorisinggridclasses",
                               {'GRID': svm_class_result,
                                'CLASS_ALL': 1, 'CLASS_ID': 0, 'SPLIT': 1, 'POLYGONS': lulc_vect})

                QMessageBox.information(self, self.tr("Finished"), self.tr("SVM classification completed."))


            if self.methodLayerCombo.currentText()=='RF':
                rf_class = Processing.runAlgorithm("r:classification",
                                        {'img': composite,
                                         'trainData': inputTraining,
                                         'responseCol': 'Classe', 'nsamples': 1000,
                                         'output': 'TEMPORARY_OUTPUT'})
                rf_class_result = rf_class['output']

                lulc_rf_vect = QFileInfo(QgsApplication.qgisUserDatabaseFilePath()).path() + "/lulc_rf_vect"

                Processing.runAlgorithm("saga:vectorisinggridclasses",
                                        {'GRID': rf_class_result,
                                         'CLASS_ALL': 1, 'CLASS_ID': 0, 'SPLIT': 1, 'POLYGONS': lulc_rf_vect})

                QMessageBox.information(self, self.tr("Finished"), self.tr("RF classification completed."))

        statistics = QFileInfo(QgsApplication.qgisUserDatabaseFilePath()).path() + "/statistics"
        if self.comboboxsuper.currentText()=='Unsupervised':
            kmeans = Processing.runAlgorithm("saga:kmeansclusteringforgrids",
                           {'GRIDS': [composite], 'METHOD': 1,
                            'NCLUSTER': 10, 'MAXITER': 0, 'NORMALISE': False, 'OLDVERSION': False, 'UPDATEVIEW': True,
                            'CLUSTER': 'TEMPORARY_OUTPUT',
                            'STATISTICS': statistics })

            kmeans_class = kmeans['CLUSTER']

            lulc_kmeans_vect = QFileInfo(QgsApplication.qgisUserDatabaseFilePath()).path() + "/lulc_kmeans_vect"

            Processing.runAlgorithm("saga:vectorisinggridclasses",
                                    {'GRID': kmeans_class,
                                     'CLASS_ALL': 1, 'CLASS_ID': 0, 'SPLIT': 1, 'POLYGONS': lulc_kmeans_vect})

            QMessageBox.information(self, self.tr("Finished"), self.tr("KMeans classification completed."))

