#******************************************************************************
#
# Freewat
# ---------------------------------------------------------
#
#
# Copyright (C) 2014 - 2015 Iacopo Borsi (iacopo.borsi@tea-group.com)
#
# This source 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.
#
# This code is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# A copy of the GNU General Public License is available on the World Wide Web
# at <http://www.gnu.org/licenses/>. You can also obtain it by writing
# to the Free Software Foundation, 51 Franklin Street, Suite 500 Boston,
# MA 02110-1335 USA.
#
#******************************************************************************
# The main part of this script has been taken from
#  GridderDialog
#                                 A QGIS plugin
# BUILDS 2D grids for finite difference
#                             -------------------
#        begin                : 2013-04-08
#        copyright            : (C) 2013 by Pryet
#        email                : alexandre.pryet@ensegid.fr
# ***************************************************************************/


from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
import os
from PyQt4 import QtGui, uic
import freewat.ftools_utils
import freewat.createGrid_utils
import math ## ACRESCENTADO
import numpy as np
from ..freewat_utils import *
from ..sqlite_utils import getTableNamesList, uploadQgisVectorLayer
from ..logger import Logger
#

class QGridderDialog(QDialog):
    def __init__(self,iface):

    # Set up the user interface from Designer.
     	QDialog.__init__(self)
        uic.loadUi(os.path.join(os.path.dirname(__file__), 'ui/ui_createGrid.ui'), self)

        self.iface = iface

        # Set up widgets
        self.checkRatio.setCheckState(Qt.Checked)
        self.checkLoadLayer.setCheckState(Qt.Checked)
    ##self.checkDivideRatio.setCheckState(Qt.Checked)
    ##self.checkTopo.setCheckState(Qt.Checked)

        # Connect buttons
        QObject.connect(self.buttonUpdateFromLayer, SIGNAL("clicked()"), self.update_from_layer)
        QObject.connect(self.buttonUpdateFromCanvas, SIGNAL("clicked()"), self.update_from_canvas)
        #QObject.connect(self.buttonBrowse, SIGNAL("clicked()"), self.out_file)


        #QObject.connect(self.buttonWriteGrid, SIGNAL("clicked()"), self.run_write_grid)
        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.run_write_grid)

    ##  QObject.connect(self.buttonRegularRefile, SIGNAL("clicked()"), self.run_regular_refine)
    ##  QObject.connect(self.buttonExport, SIGNAL("clicked()"), self.run_export)
    ##  QObject.connect(self.buttonProceedNumbering, SIGNAL("clicked()"), self.run_preprocessing)

        # Connect actions
        # Connect actions

    ##  QObject.connect(self.sboxDivideHoriz, SIGNAL("valueChanged(int)"), self.set_divide_vert)

        QObject.connect(self.textXmin, SIGNAL("textChanged(const QString &)"), self.estim_number_grid_cells)
        QObject.connect(self.textXmax, SIGNAL("textChanged(const QString &)"), self.estim_number_grid_cells)
        QObject.connect(self.textYmin, SIGNAL("textChanged(const QString &)"), self.estim_number_grid_cells)
        QObject.connect(self.textYmax, SIGNAL("textChanged(const QString &)"), self.estim_number_grid_cells)
        QObject.connect(self.sboxXres, SIGNAL("valueChanged(double)"), self.estim_number_grid_cells)
        QObject.connect(self.sboxYres, SIGNAL("valueChanged(double)"), self.estim_number_grid_cells)
        QObject.connect(self.sboxXres, SIGNAL("valueChanged(double)"), self.set_Yres)

        self.buttonImportFromTxt.clicked.connect(self.create_grid_from_TXT)  ## ACRESCENTADO
        self.toolBrowseButton.clicked.connect(self.outFiletxt)  ## ACRESCENTADO

        # Populate layer list
    ##  for modelName in ['Modflow','Newsam']:
    ##      self.listModelName.addItem(unicode(modelName))

        # Populate model name list
        self.populate_layers(self.listSourceLayer)
    ##  self.populate_layers(self.listGridLayer)


        #Populate Model combobox

        self.cmbModelName.clear()
        layerNameList = getVectorLayerNames()
        (modelNameList, pathList) =  getModelsInfoLists(layerNameList)
        self.cmbModelName.addItems(modelNameList)

        # Get update extents from map canvas
        self.update_from_canvas()

        # Set up validators
        self.textXmin.setValidator(QDoubleValidator(self.textXmin))
        self.textXmax.setValidator(QDoubleValidator(self.textXmax))
        self.textYmin.setValidator(QDoubleValidator(self.textYmin))
        self.textYmax.setValidator(QDoubleValidator(self.textYmax))

    	self.defaultRes=float(10)
    	self.sboxXres.setValue(self.defaultRes)
    	self.sboxYres.setValue(self.defaultRes)

    	# Init labels
    ##	self.labelIterations.hide()
    ##	self.labelIter.hide()

    	# Init variables
    	#self.OutFileName = 'grid.shp'
    	self.OutFileName = self.textEdit.text()
    	self.encoding = 'System'



    #  ======= Update automatically when 1:1 ratio is checked
    def set_Yres(self, value):
        if self.checkRatio.isChecked():
            self.sboxYres.setValue(value)

##    def set_divide_vert(self, value):
##	if self.checkDivideRatio.isChecked():
##            self.sboxDivideVert.setValue(value)

    #  ======= Choose output shape file
    def out_file(self):
        self.textOutFilename.clear()
        ( self.OutFileName, self.encoding ) = freewat.ftools_utils.saveDialog( self )
        if self.OutFileName is None or self.encoding is None:
            return
        self.textOutFilename.setText( self.OutFileName  )

    #  ======= Populate input layer list
    def populate_layers( self,listOfLayers):
        listOfLayers.clear()
        layermap = QgsMapLayerRegistry.instance().mapLayers()

	if type(layermap)==dict :
	    if len(layermap) > 0:
		listOfLayers.setEnabled(True)
		for name, layer in layermap.iteritems():
		    listOfLayers.addItem( unicode( layer.name() ) )
		    if layer == self.iface.activeLayer():
			listOfLayers.setCurrentIndex( self.listSourceLayer.count() -1 )
	    else :
		listOfLayers.setEnabled(False)
	else :
	    listOfLayers.setEnabled(False)


    #  ======= Update extents from layer
    def update_from_layer( self ):
        mLayerName = self.listSourceLayer.currentText()
        if not mLayerName == "":
            mLayer = freewat.ftools_utils.getMapLayerByName( unicode( mLayerName ) )
            # get layer extents
            boundBox = mLayer.extent()
            self.update_extents( boundBox )

    #  ======= Update extents from current map canvas
    def update_from_canvas( self ):
        canvas = self.iface.mapCanvas()
        boundBox = canvas.extent()
        self.update_extents( boundBox )

    #  ======= Update extents in text boxes
    def update_extents( self, boundBox ):
        self.textXmin.setText( unicode( boundBox.xMinimum() ) )
        self.textYmin.setText( unicode( boundBox.yMinimum() ) )
        self.textXmax.setText( unicode( boundBox.xMaximum() ) )
        self.textYmax.setText( unicode( boundBox.yMaximum() ) )

    # ======= Estimate number of grid cells
    def estim_number_grid_cells(self,value = ' '):

	try :
	    Xmin = float( self.textXmin.text() )
	    Xmax = float( self.textXmax.text() )
	    Ymin = float( self.textYmin.text() )
	    Ymax = float( self.textYmax.text() )
	    Xres = float( self.sboxXres.value() )
	    Yres = float( self.sboxYres.value() )
	    if Xres != 0 and Yres !=0:
		Nx = round((Xmax - Xmin) / Xres)
		Ny = round((Ymax - Ymin) / Yres)
		N = abs(int(Nx*Ny))
	    else :
		N = ' '
	except :
	    N = ' '

	self.labelNumberCells.setText( unicode(N) )

    # function to choose the txt file  ## ACRESCENTADO
    def outFiletxt(self):  ## ACRESCENTADO
        self.OutFilePath = fileDialog(self)  ## ACRESCENTADO
        self.txtDirectory.setText(self.OutFilePath)  ## ACRESCENTADO

	
    # ======= Create grid from TXT file =========================  ## ACRESCENTADO
    def create_grid_from_TXT(self,value = ' '):  ## ACRESCENTADO
        try:  ## ACRESCENTADO
            file = self.txtDirectory.text()  ## ACRESCENTADO
            f = open(file, 'r')  ## ACRESCENTADO
            f.readline() #Reads one heading line with text to be ignored ## ACRESCENTADO
            valor = f.readline() ## ACRESCENTADO
            if self.cmb_decsep.currentText() == ',':  ## ACRESCENTADO
                valor = valor.replace(',','.')  ## ACRESCENTADO
            if self.cmb_colsep.currentText() == ';':  ## ACRESCENTADO
                valor = valor.replace(';',',')  ## ACRESCENTADO
                
            x_world, y_world, x_model, y_model, angle = (float(val) for val in valor.split(","))  ## ACRESCENTADO
            # x_world = x world origin coordinate of the model  ## ACRESCENTADO
            # y_world = y world origin coordinate of the model  ## ACRESCENTADO
            # x_model = x model origin coordinate of the model  ## ACRESCENTADO
            # y_model = y model origin coordinate of the model  ## ACRESCENTADO
            # angle = azimuth of the Y direction (angle between north and Y direction of the model in degrees)  ## ACRESCENTADO
            angle = math.radians(angle) #converts degrees to radians  ## ACRESCENTADO
            ncols = int(f.readline())  ## ACRESCENTADO
            x_node = []  ## ACRESCENTADO
            for i in range(0,ncols+1):  ## ACRESCENTADO
                valor = f.readline()  ## ACRESCENTADO
                if self.cmb_decsep.currentText() == ',':  ## ACRESCENTADO
                    valor = valor.replace(',','.')  ## ACRESCENTADO
                x_node.append(float(valor))  ## ACRESCENTADO
            nrows = int(f.readline())  ## ACRESCENTADO
            y_node = []  ## ACRESCENTADO
            for j in range(0,nrows+1):  ## ACRESCENTADO
                valor = f.readline()  ## ACRESCENTADO
                if self.cmb_decsep.currentText() == ',':  ## ACRESCENTADO
                    valor = valor.replace(',','.')  ## ACRESCENTADO
                y_node.append(float(valor))  ## ACRESCENTADO
            f.close()  ## ACRESCENTADO
            xmin, ymin = freewat.createGrid_utils.transf(x_world, y_world, x_model, y_model, angle, x_node[0], y_node[0])  ## ACRESCENTADO
            xmax, ymax = freewat.createGrid_utils.transf(x_world, y_world, x_model, y_model, angle, x_node[ncols], y_node[nrows])  ## ACRESCENTADO
            self.textXmin.setText( str(xmin) )  ## ACRESCENTADO
            self.textYmin.setText( str(ymin) )  ## ACRESCENTADO
            self.textXmax.setText( str(xmax) )  ## ACRESCENTADO
            self.textYmax.setText( str(ymax) )  ## ACRESCENTADO
            self.sboxXres.setValue( (xmax - xmin) / ncols )  ## ACRESCENTADO 
            self.sboxYres.setValue( (ymax - ymin) / nrows )  ## ACRESCENTADO
            self.labelNumberCells.setText( str(ncols * nrows) )  ## ACRESCENTADO
	except:  ## ACRESCENTADO
            QMessageBox.information(self, self.tr("TXT file"),  ## ACRESCENTADO
		self.tr("Wrong TXT file format or delimeters. Browse and select the correct TXT format file.")  ## ACRESCENTADO
			)  ## ACRESCENTADO

    # ======= Build grid ========================================
    def run_write_grid(self):


	# Check input data
        if (self.textXmin.text() == "" or self.textXmax.text() == "" or
		self.textYmin.text() == "" or self.textYmax.text() == ""):
            QMessageBox.information(self, self.tr("Gridder"),
		    self.tr("Please specify valid extent coordinates")
		    )
        elif self.textEdit.text() == "":
            QMessageBox.information(self, self.tr("Gridder"),
		    self.tr("Please specify valid output layer name")
		    )
	elif self.sboxXres.value() == 0:
            QMessageBox.information(self, self.tr("Gridder"),
		    self.tr("Please specify valid resolution")
		    )
	elif float( self.textXmin.text() ) >= float( self.textXmax.text() ) or \
		float( self.textYmin.text() ) >= float( self.textYmax.text() ):
		    QMessageBox.information(self, self.tr("Gridder"),
		    self.tr("Check extent coordinates")
		    )
	else:
            try:
                boundBox = QgsRectangle(
                float( self.textXmin.text() ),
                float( self.textYmin.text() ),
                float( self.textXmax.text() ),
                float( self.textYmax.text() ) )
	    except:
                QMessageBox.information(self, self.tr("Vector grid"),
			self.tr("Invalid extent coordinates entered")
			)

            if len(self.txtDirectory.text()) > 0: ##ACRESCENTADO
                file = self.txtDirectory.text()  ## ACRESCENTADO
                f = open(file, 'r')  ## ACRESCENTADO
                f.readline() #Reads one heading line  ## ACRESCENTADO
                valor = f.readline() ## ACRESCENTADO
                if self.cmb_decsep.currentText() == ',':  ## ACRESCENTADO
                    valor = valor.replace(',','.')  ## ACRESCENTADO
                if self.cmb_colsep.currentText() == ';':  ## ACRESCENTADO
                    valor = valor.replace(';',',')  ## ACRESCENTADO
                x_world, y_world, x_model, y_model, angle = (float(val) for val in valor.split(","))  ## ACRESCENTADO
                angle = math.radians(angle) #converts degrees to radians  ## ACRESCENTADO
                ncols = int(f.readline())  ## ACRESCENTADO
                x_node = []  ## ACRESCENTADO
                for i in range(0,ncols+1):  ## ACRESCENTADO
                    valor = f.readline()  ## ACRESCENTADO
                    if self.cmb_decsep.currentText() == ',':  ## ACRESCENTADO
                        valor = valor.replace(',','.')  ## ACRESCENTADO
                    x_node.append(float(valor))  ## ACRESCENTADO
                nrows = int(f.readline())  ## ACRESCENTADO
                y_node = []  ## ACRESCENTADO
                for j in range(0,nrows+1):  ## ACRESCENTADO
                    valor = f.readline()  ## ACRESCENTADO
                    if self.cmb_decsep.currentText() == ',':  ## ACRESCENTADO
                        valor = valor.replace(',','.')  ## ACRESCENTADO
                    y_node.append(float(valor))  ## ACRESCENTADO
                f.close()  ## ACRESCENTADO
                n = nrows  ## ACRESCENTADO
                m = ncols  ## ACRESCENTADO
            else: #This block corresponds to the original code that however was indented  ## ACRESCENTADO

                Xres = self.sboxXres.value()  ## ORIGINAL CODE, INDENTED
                Yres = self.sboxYres.value()  ## ORIGINAL CODE, INDENTED

                # Compute number of elements  ## ORIGINAL CODE, INDENTED


                n = int( round( (boundBox.yMaximum() - boundBox.yMinimum()) / Yres ) )  ## ORIGINAL CODE, INDENTED
                m = int( round( (boundBox.xMaximum() - boundBox.xMinimum()) / Xres ) )  ## ORIGINAL CODE, INDENTED

                # Adjust bounding box to respect Yres and Xres with linspace  ## ORIGINAL CODE, INDENTED
                boundBox.setXMaximum( boundBox.xMinimum() + m*Xres )  ## ORIGINAL CODE, INDENTED
                boundBox.setYMaximum( boundBox.yMinimum() + n*Yres )  ## ORIGINAL CODE, INDENTED

                if n*m <= 0 :  ## ORIGINAL CODE, INDENTED
                    Logger.warning(self, self.tr("Gridder"),  ## ORIGINAL CODE, INDENTED
                    self.tr("Invalid extent or resolution entered")  ## ORIGINAL CODE, INDENTED
                    )  ## ORIGINAL CODE, INDENTED
                    return  ## ORIGINAL CODE, INDENTED

	    # TO DO : Here, you should check whether elements  is correct...
	    # Or add it directly as information in the grid resolution frame
            QApplication.setOverrideCursor(Qt.WaitCursor)

	    # ------------ Input data validated, build Grid


	    # If a source layer is defined, retrieve CRS
	    if freewat.ftools_utils.getMapLayerByName(unicode(self.listSourceLayer.currentText())) != None :
		crs = freewat.ftools_utils.getMapLayerByName(unicode(self.listSourceLayer.currentText())).crs()
		if not crs.isValid():
		    crs = None
	    else :
		crs = None

	    # Initialize field for base feature
	    # TO DO : add useful attributes
	    #fields = {0:QgsField("ID", QVariant.Int)}
	    fields = QgsFields()
	    fields.append(QgsField("ID", QVariant.Int))
	    # Initialize base rectangle feature
	    rectFeat = QgsFeature()
	    rectGeom = QgsGeometry()
	    rectFeat.setGeometry(rectGeom.fromRect(boundBox))
	    #rectFeat.setAttributeMap(fields)
	    rectFeat.initAttributes(1)
	    idVar = 0
	    #rectFeat.addAttribute(0, QVariant(idVar))
	    rectFeat.setAttribute(0, idVar)

	    # if the file exits, remove it
	    check = QFile(self.OutFileName)
	    if QFile(self.OutFileName).exists():
		if not QgsVectorFileWriter.deleteShapeFile(self.OutFileName):
		    return

	    # Load shape file writer
	    #writer = QgsVectorFileWriter(unicode(self.textOutFilename.text()), self.encoding, fields, QGis.WKBPolygon, crs)


        #match the exact model trough the list of all models
        layerNameList = getVectorLayerNames()
        (modelNameList, pathList) =  getModelsInfoLists(layerNameList)
        modelName = self.cmbModelName.currentText()
        (pathfile, nsp) = getModelInfoByName(modelName)
        dbname = os.path.join(pathfile, modelName + '.sqlite')
        db = [os.path.basename(dbname).replace('.sqlite', '')]
        for i in db:
            if i in modelNameList:
                modelName = 'modeltable_' + str(i)

        model = getVectorLayerByName(modelName)
        for ft in model.getFeatures():
            crs = ft['crs']

        # Create Grid as memory layer
        vl = QgsVectorLayer("Polygon?crs=" + crs, "grid", "memory")
        pr = vl.dataProvider()
        fld = vl.dataProvider().fields()

        for fld in fields:
            res = pr.addAttributes([fld])

        vl.updateFields()
        vl.commitChanges()

        if len(self.txtDirectory.text()) > 0: ##ACRESCENTADO
            # Call function to make irregular grid  ## ACRESCENTADO
            freewat.createGrid_utils.make_irrgrid(rectFeat, n, m, x_node, y_node, x_world, y_world,  ## ACRESCENTADO
                                                  x_model, y_model, angle, pr, self.progressBarBuildGrid)  ## ACRESCENTADO
        else:  ## ACRESCENTADO
            # Call function to make grid  ## ORIGINAL CODE, INDENTED
            freewat.createGrid_utils.make_rgrid(rectFeat, n, m, pr, self.progressBarBuildGrid)  ## ORIGINAL CODE, INDENTED

        # Delete writer
        #del writer

        # Post-operation information
        QApplication.restoreOverrideCursor()
        #QMessageBox.information(self, self.tr("Generate Vector Grid"), "Created output shapefile:\n" + unicode(self.OutFileName) + "\n")
        # Load and use the grid layer



##     # Load output layer if it is not already loaded
##	    if self.checkLoadLayer.isChecked():
##		# list currently loaded layer. If the layer is loaded, unload it.
##		for (name,layer) in	QgsMapLayerRegistry.instance().mapLayers().iteritems():
##		    # Note : reload() doesn't work.
##		    if layer.source()==self.OutFileName:
##			QgsMapLayerRegistry.instance().removeMapLayers( layer.id() )
##
##		# load layer
##		freewat.ftools_utils.addShapeToCanvas( self.OutFileName )
##		# update layer list in plugin
##		self.populate_layers(self.listSourceLayer)
##		self.populate_layers(self.listGridLayer)
        # Load the grid layer and use it for numbering


        #Retrieve information of the used model

        if len(self.txtDirectory.text()) > 0: ## ACRESCENTADO
            freewat.createGrid_utils.irrgrid_numbering(vl)  ## ACRESCENTADO
        else:  ## ACRESCENTADO
            #gridLayer = QgsVectorLayer(self.OutFileName, unicode(self.OutFileName), 'ogr')  ## ORIGINAL CODE, INDENTED
            freewat.createGrid_utils.rgrid_numbering(vl)  ## ORIGINAL CODE, INDENTED

        #QMessageBox.information(self, self.tr("Generate Vector Grid"), "Grid created and added to the Legend \n" + unicode(self.OutFileName) + "\n")

        #freewat.ftools_utils.addShapeToCanvas( self.OutFileName )
        #QgsMapLayerRegistry.instance().addMapLayer(gridLayer)

        # Load data for SpatiaLite
        modelName = self.cmbModelName.currentText()

        (pathfile, nsp) = getModelInfoByName(modelName)

        name = self.textEdit.text() + '_grid'

        dbname = os.path.join(pathfile, modelName + '.sqlite')
        tableList = getTableNamesList(dbname)
        layerName = name

        if layerName in tableList:
            Logger.warning(self, self.tr('Warning!'), self.tr('Table %s already exists!' % layerName))

        uploadQgisVectorLayer(dbname, vl, name)

        uri = QgsDataSourceURI()
        uri.setDatabase(dbname)
        schema = ''
        table = name
        geom_column = "Geometry"
        uri.setDataSource(schema, table, geom_column)
        display_name = table

        vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')

        Logger.information(self, self.tr("Generate Grid"), "Grid created and added to the Legend")

        QgsMapLayerRegistry.instance().addMapLayer(vlayer)
        self.reject()
