#coding=utf-8
#Copyright (C) 2015 IDAEA-CSIC
#
#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. This program is distributed in the hope that it will be useful, but
#ITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
#PURPOSE. See the GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License along with this program; if not, write to
#the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
'''
:copyright: Copyright (C) 2015 IDAEA-CSIC
:authors: V. Velasco Mansilla, L.M. de Vries, A. Nardi, R. Criollo, E. Vázquez Suñé
:contact: enric.vazquez@idaea.csic.es
:license: GPL General Public License, version 2 or any later version (http://opensource.org/licenses/GPL-2.0)
'''
from qgis.core import QgsField, QgsMapLayerRegistry, QgsFeatureRequest, QgsFeature, QgsProject
from PyQt4.QtGui import QIcon, QMessageBox
from PyQt4.Qt import QSqlQueryModel, QSqlQuery
from PyQt4.QtCore import QVariant

from form.AKFormHydroUnitSelection import AKFormHydroUnitSelection
from AKFeatureCustomChartHydro import AKFeatureCustomChartHydro
from AKSettings import TABLES

class AKFeatureMapHydroSurface(AKFeatureCustomChartHydro):
    '''This features generates maps with the top and bottom heights for the selected hydrogeological unit'''
    def __init__(self, settings, iface, parent=None):
        super(AKFeatureMapHydroSurface, self).__init__(settings, iface, windowTitle='Hydrogeological Surfaces', parent=parent)
        self.m_icon = QIcon(settings.getIconPath('geoMap.png'))
        self.m_text = 'Hydrogeological Units Map'
        self.m_form = AKFormHydroUnitSelection(iface, self.parent())
        self.m_form.accepted.connect(self.onUnitSelected)
        self.m_form.btnCreateMap.clicked.connect(self.onUnitSelected)
        self.m_form.btnClose.clicked.connect(self.onClose)
        self.m_form.finished.connect(self.onClose)
        self.m_form.cmbUnit.currentIndexChanged.connect(self.onUnitChanged)
        self.defineSQLQueries()
        self.unitId = -1

    def onClose(self):
        self.m_form.close()

    def defineSQLQueries(self):
        super(AKFeatureMapHydroSurface, self).defineSQLQueries()
        self.sqlSelAllHydroUnits =  "SELECT " \
                                        "HU.id, " \
                                        "HU.hydroUnit, " \
                                        "HU.descriptionEN, " \
                                        "LHT.hydroUnitType," \
                                        "LHT.descriptionEN UnitDescription," \
                                        "HU.otherHydroUnitsDetails, " \
                                        "HU.observations " \
                                    "FROM " + \
                                        TABLES.HYDROUNITS + " HU, " + \
                                        TABLES.L_HYDROUNITTYPE + " LHT " \
                                    "WHERE " \
                                        "HU.hydroUnitType = LHT.id " \
                                    "ORDER BY HU.hydroUnit COLLATE NOCASE;"

        self.sqlSelUnitPoints = "SELECT " \
                                    "P.id AS PointId, " \
                                    "P.point, " \
                                    "WHU.topLength, " \
                                    "WHU.bottomLength " \
                                "FROM " + \
                                    TABLES.WELLS_HYDROUNIT + " WHU, " + \
                                    TABLES.WELLS + " W, " + \
                                    TABLES.POINTS + " P " + \
                                "WHERE " \
                                    "WHU.hydroUnitId = ? " \
                                    "AND WHU.wellId = W.id " \
                                    "AND W.pointId = P.id " \
                                "ORDER BY point COLLATE NOCASE;"

    def initialize(self):
        self.currentDB = self.m_settings.getCurrentDB()
        self.getHydroUnitData()
        self.m_form.show()

    def onUnitSelected (self):
        unitCombo = self.m_form.cmbUnit
        curIndex = unitCombo.currentIndex()
        self.unitId = unitCombo.model().data(unitCombo.model().index(curIndex,0))
        rowIndex = unitCombo.currentIndex()
        self.createMap(rowIndex)

    def createMap(self, rowIndex):
        unitCombo = self.m_form.cmbUnit
        allPoints = self.getAllUnitPoints(self.unitId)
        selectedUnit = unitCombo.model().data(unitCombo.model().index(rowIndex,1))
        attrFields = [QgsField("topLength", QVariant.Double),
                      QgsField("bottomLength",  QVariant.Double)]

        root = QgsProject.instance().layerTreeRoot()
        groupName = self.generateNewName("Hydrogeological Units")
        newGroupNode = root.addGroup(groupName)

        labelPlacement = 0
        pointsLayer = self.m_settings.m_availableTables[TABLES.POINTS]["layerObject"]
        pointsProjection = self.getProjection(pointsLayer)
        newLayer = self.addVectorLayer("Point", selectedUnit, pointsProjection, attrFields, labelPlacement)

        curProvider = newLayer.dataProvider()
        for pointId in allPoints:
            curValues = allPoints[pointId]
            pointFeature = pointsLayer.getFeatures(QgsFeatureRequest().setFilterFid( pointId ) )
            nextFeat = pointFeature.next()
            feature = QgsFeature()
            feature.setGeometry(nextFeat.geometry())
            point = curValues[0]
            topLength = curValues[1]
            bottomLength = curValues[2]
            feature.setAttributes([point, topLength,bottomLength])
            curProvider.addFeatures([feature])
        self.finalizeLayer(newLayer, "topLength", newGroupNode, paramLimits=None)
        QMessageBox.information(self.iface.mainWindow(),
            "Finished creating the requested map.",
            "The following map has been generated: \n\n- " + selectedUnit)

    def onUnitChanged(self):
        unitCombo = self.m_form.cmbUnit
        curIndex = unitCombo.currentIndex()
        description = unitCombo.model().data(unitCombo.model().index(curIndex,2))
        unitType = unitCombo.model().data(unitCombo.model().index(curIndex,3))
        typeDescription = unitCombo.model().data(unitCombo.model().index(curIndex,4))
        details = unitCombo.model().data(unitCombo.model().index(curIndex,5))
        observations = unitCombo.model().data(unitCombo.model().index(curIndex,6))
        if(description != None):
            self.m_form.txtDescription.setPlainText(description)
        else:
            self.m_form.txtDescription.clear()
        if(unitType != None):
            self.m_form.txtType.setText(unitType)
        else:
            self.m_form.txtType.clear()
        if(typeDescription != None):
            self.m_form.txtTypeDescription.setPlainText(typeDescription)
        else:
            self.m_form.txtTypeDescription.clear()
        if(details != None):
            self.m_form.txtDetails.setPlainText(details)
        else:
            self.m_form.txtDetails.clear()
        if(observations != None):
            self.m_form.txtObservations.setPlainText(observations)
        else:
            self.m_form.txtObservations.clear()

    def getHydroUnitData(self):
        query = QSqlQuery(self.currentDB)
        query.prepare(self.sqlSelAllHydroUnits)
        query.exec_()
        unitModel = QSqlQueryModel(self.m_form)
        unitModel.setQuery(query)
        while unitModel.canFetchMore():
            unitModel.fetchMore()

        self.m_form.cmbUnit.setModel(unitModel)
        HYDRO_UNIT = 1
        self.m_form.cmbUnit.setModelColumn(HYDRO_UNIT)

    def getAllUnitPoints(self, unitId):
        query = QSqlQuery(self.currentDB)
        query.prepare(self.sqlSelUnitPoints)
        query.addBindValue(unitId)
        query.exec_()
        pointInfo = {}
        while query.next():
            pointId = query.value(0)
            point = query.value(1)
            topLength = query.value(2)
            bottomLength = query.value(3)
            pointInfo[pointId] = [point,topLength,bottomLength]
        return pointInfo