#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 QgsProject, QgsLayerTreeGroup, QgsVectorLayer, QgsField
from qgis.core import QgsMapLayerRegistry, QgsGraduatedSymbolRendererV2, QgsRendererRangeV2
from PyQt4.QtCore import QObject, QVariant
from PyQt4.Qt import QModelIndex, QItemSelectionModel, QItemSelection
from PyQt4.QtGui import QFileDialog, QMessageBox 
import os
import pyexcel
import pyexcel.ext.xlsx
import pyexcel.ext.xls
import pyexcel.ext.ods

class AKFeature (QObject):
    """
    Base Class for AkvaGIS Features
    
    Each AKFeature has the following (optional) functionality:
     - initialize()
     - run() 
    
    This class contains common functionality like:
     - saving table data to spreadsheet files
     - selecting all/first rows in table views
     - generate new file names
     - addding QGIS vector layers
    """
    def __init__(self, iface, parent = None):
        self.iface = iface
        if parent !=None:
            super(AKFeature, self).__init__(parent)
        else:
            super(AKFeature, self).__init__(iface.mainWindow())                

    def run(self):    
        self.initialize()

    def selectFirstInView(self, view):
        model = view.model()
        numOfRows = model.rowCount()
        numOfCols = model.columnCount()
        if(numOfRows > 0):
            topLeft = model.index(0, 0, QModelIndex())
            bottomRight = model.index(0, numOfCols-1, QModelIndex());
            selection = QItemSelection(topLeft, bottomRight);
            view.selectionModel().select(selection, QItemSelectionModel.Select)
            view.setFocus()

    def selectAllInView(self, view, selectMode):
        model = view.model()
        numOfRows = model.rowCount()
        numOfCols = model.columnCount()
        topLeft = model.index(0, 0, QModelIndex())
        bottomRight = model.index(numOfRows-1, numOfCols-1, QModelIndex())
        selection = QItemSelection(topLeft, bottomRight)
        view.selectionModel().select(selection, selectMode)
        view.setFocus()
        
    def saveTable(self, form, headers, contents):
        data = [headers]
        data.extend(contents)
        
        files_types = "LibreOffice (*.ods);;Excel (*.xls);;CSV (*.csv)"
        filename = QFileDialog.getSaveFileName(form, "Save file", os.getenv("HOME"), files_types)
        
        if len(filename)==0:
            return
        pyexcel.save_as(array=data, dest_file_name=filename)
        
    def groupExists(self, groupName):
        root = QgsProject.instance().layerTreeRoot()
        for child in root.children():
            if isinstance(child, QgsLayerTreeGroup):
                if(groupName == child.name()):
                    return True
        return False

    def generateNewName(self, base):
        newName = base
        if(self.groupExists(base)):
            i = 1
            while(self.groupExists(newName)):
                newName = base + "_" + str(i) 
                i = i + 1
        return newName

    def confirmClosing(self):
        curGroup = self.m_settings.dbGroup
        msg = "Are you sure you want to close and remove the \""+ curGroup +"\" group?"
        ret = QMessageBox.question(self.iface.mainWindow(), 'Message',
            msg, QMessageBox.Yes | 
            QMessageBox.No, QMessageBox.No)
        return ret
    
    def confirmReplacement(self):
        msg = "This file already exists! Are you sure you want to replace it?"
        ret = QMessageBox.question(self.iface.mainWindow(), 'Warning',
            msg, QMessageBox.Yes | 
            QMessageBox.No, QMessageBox.No)
        return ret

    def closeDatabase(self):
        curGroup = self.m_settings.dbGroup
        root = QgsProject.instance().layerTreeRoot()
        groupNode = root.findGroup(curGroup)
        root.removeChildNode(groupNode)
        self.m_settings.currentDB = None
        self.m_settings.dbGroup = None

    def addLabel(self, layer, placement = 0):
        layer.setCustomProperty("labeling", "pal")
        layer.setCustomProperty("labeling/enabled", "true")
        layer.setCustomProperty("labeling/fieldName", "point")
        layer.setCustomProperty("labeling/fontSize", "10")
        layer.setCustomProperty("labeling/dist", "0.4")
        layer.setCustomProperty("labeling/fontFamily", "Arial")    
        layer.setCustomProperty("labeling/placement", placement);    

    def getProjection(self, layer):
        crs = layer.crs()
        return crs.geographicCRSAuthId()

    def addVectorLayer(self, layerType, name, projection, fields=[], labelPlacement=1):
        layer = QgsVectorLayer(layerType + "?crs=" + projection + "&index=yes", name, "memory")
        pr = layer.dataProvider()
        layer.startEditing()
        fixedFields = [QgsField("point", QVariant.String)]
        fields = fixedFields + fields
        pr.addAttributes(fields)
        layer.updateFields() # tell the vector layer to fetch changes from the provider
        self.addLabel(layer, placement=labelPlacement)
        return layer

    def addLayerToLayersWindow(self, layer, parentNode=None):
        QgsMapLayerRegistry.instance().addMapLayer(layer, False)
        if(parentNode != None):
            treeLayerNode = parentNode.addLayer(layer)
            treeLayerNode.setVisible(False)

    def finalizeLayer(self, newLayer, targetField, groupNode, paramLimits=None, labels=[], addLegend = True):
        if(addLegend):
            myRenderer = QgsGraduatedSymbolRendererV2()
            myRenderer.setClassAttribute(targetField)
            myRenderer.setMode(QgsGraduatedSymbolRendererV2.EqualInterval)
            if paramLimits == None:
                numIntervals = newLayer.featureCount()
                if numIntervals > 4:
                    numIntervals = 4                
                myRenderer.updateClasses(newLayer, QgsGraduatedSymbolRendererV2.EqualInterval, numIntervals)
            else:
                if len(paramLimits) > 0:
                    rangeList = []
                    for i in range(len(paramLimits)-1):
                        limitRange = QgsRendererRangeV2()
                        if paramLimits[i] != None:
                            limitRange.setLowerValue(paramLimits[i])
                        if paramLimits[i+1] != None:
                            limitRange.setUpperValue(paramLimits[i+1])
                        rangeList.append(limitRange)
                    for i in range(len(rangeList)):
                        rangeList[i].setLabel(labels[i])
                    myRenderer.updateClasses(newLayer, QgsGraduatedSymbolRendererV2.EqualInterval, len(rangeList))
                    for rangeIndex in range(len(rangeList)):
                        curRange = rangeList[rangeIndex]
                        myRenderer.updateRangeLowerValue (rangeIndex, curRange.lowerValue())
                        myRenderer.updateRangeUpperValue (rangeIndex, curRange.upperValue())
                        myRenderer.updateRangeLabel(rangeIndex, curRange.label())
            newLayer.setRendererV2(myRenderer)
        newLayer.updateExtents()
        self.addLayerToLayersWindow(newLayer, groupNode)

    def finalizeLayers(self, newlayers, targetField, groupNode, paramLimits=None, labels=[], addLegend = True):
        for paramId in newlayers:
            newLayer = newlayers[paramId]
            limits = None
            if paramLimits != None:
                limits = paramLimits[paramId]
            self.finalizeLayer(newLayer, targetField, groupNode, limits, labels, addLegend)