# -*- coding: utf-8 -*-

#******************************************************************************
#
# 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.
#
#******************************************************************************

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
import os
from PyQt4 import QtGui, uic
from freewat.freewat_utils import getVectorLayerByName, getVectorLayerNames, fileDialog, getModelsInfoLists, getModelInfoByName, getModelNlayByName, ComboStyledItemDelegate
from freewat.mdoCreate_utils import createModelLayer
from freewat.sqlite_utils import getTableNamesList, uploadCSV
from pyspatialite import dbapi2 as sqlite3
import numpy as np

class CreateParams2DLayerDialog(QDialog):
    def __init__(self, iface):
        QDialog.__init__(self)
        self.iface = iface
        uic.loadUi(os.path.join( os.path.dirname(__file__), 'ui/ui_2DParametersLayer.ui'), self)

        self.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.createParams)

        #csv browse button
        self.toolBrowseButton.clicked.connect(self.outFilecsv)
        self.cmbModelName.currentIndexChanged.connect(self.reloadSpNums)
        #
        #
        self.cmbZoneOption_1.currentIndexChanged.connect(self.updateZoneLayer1)
        self.cmbZoneOption_2.currentIndexChanged.connect(self.updateZoneLayer2)
        self.cmbZoneOption_3.currentIndexChanged.connect(self.updateZoneLayer3)
        self.cmbZoneOption_4.currentIndexChanged.connect(self.updateZoneLayer4)
        #
        self.cmbZoneLayer_1.currentIndexChanged.connect(self.reloadZones1)
        self.cmbZoneLayer_2.currentIndexChanged.connect(self.reloadZones2)
        self.cmbZoneLayer_3.currentIndexChanged.connect(self.reloadZones3)
        self.cmbZoneLayer_4.currentIndexChanged.connect(self.reloadZones4)

        # For multiplier option to check zone option ??
##        self.cmbMultiplier_1.currentIndexChanged.connect(self.checkMultiplier)

        self.manageGui()
##
##
    def manageGui(self):
        self.cmbModelName.clear()
        self.layerNameList = getVectorLayerNames()
        self.layerNameList.sort()
        (modelNameList, pathList) =  getModelsInfoLists(self.layerNameList)

        self.cmbModelName.addItems(modelNameList)

        self.zlist = []
        for nn in self.layerNameList:
            if '_zone' in nn:
                self.zlist.append(nn)
##
##    def checkMultiplier(self):
##        if 'Yes' in self.cmbMultiplier_1.currentText():
##            self.cmbZoneOption_1.clear()

    def updateZoneLayer1(self):
        if 'Yes' in self.cmbZoneOption_1.currentText():
            self.cmbZoneLayer_1.addItems(self.zlist)
            self.reloadZones1()

    def updateZoneLayer2(self):
        if 'Yes' in self.cmbZoneOption_2.currentText():
            self.cmbZoneLayer_2.addItems(self.zlist)
            self.reloadZones2()

    def updateZoneLayer3(self):
        if 'Yes' in self.cmbZoneOption_3.currentText():
            self.cmbZoneLayer_3.addItems(self.zlist)
            self.reloadZones3()

    def updateZoneLayer4(self):
        if 'Yes' in self.cmbZoneOption_4.currentText():
            self.cmbZoneLayer_4.addItems(self.zlist)
            self.reloadZones4()


##
    def reloadSpNums(self):
        # Retrieve the model
        self.modelName = self.cmbModelName.currentText()
        (pathfile, self.nsp ) = getModelInfoByName(self.modelName)
        spList = [str(i) for i in range(1,self.nsp + 1)]

        self.cmbSp_1.clear()
        self.cmbSp_2.clear()
        self.cmbSp_3.clear()
        self.cmbSp_4.clear()

        # Model for Selecting more than one SP
        # Insert in ComboBox
        self.model = QtGui.QStandardItemModel(self.nsp, 1)# nsp rows, 1 col
        it0 = QtGui.QStandardItem('-- Select SP -- ')
        for i, sp  in enumerate(spList):
            item = QtGui.QStandardItem(str(sp))
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            if i == 0:
                item.setData(Qt.Checked, Qt.CheckStateRole)
            else:
                item.setData(Qt.Unchecked, Qt.CheckStateRole)
            self.model.setItem(i+1, 0, item)
        self.model.setItem(0,it0)
        self.cmbSp_1.setModel(self.model)
        self.cmbSp_1.setItemDelegate(ComboStyledItemDelegate())
        # 2
        self.model_2 = QtGui.QStandardItemModel(self.nsp, 1)# nsp rows, 1 col
        it0 = QtGui.QStandardItem('-- Select SP -- ')
        for i, sp  in enumerate(spList):
            item = QtGui.QStandardItem(str(sp))
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            if i == 0:
                item.setData(Qt.Checked, Qt.CheckStateRole)
            else:
                item.setData(Qt.Unchecked, Qt.CheckStateRole)
            self.model_2.setItem(i+1, 0, item)
        self.model_2.setItem(0,it0)
        self.cmbSp_2.setModel(self.model_2)
        self.cmbSp_2.setItemDelegate(ComboStyledItemDelegate())
        # 3
        self.model_3 = QtGui.QStandardItemModel(self.nsp, 1)# nsp rows, 1 col
        it0 = QtGui.QStandardItem('-- Select SP -- ')
        for i, sp  in enumerate(spList):
            item = QtGui.QStandardItem(str(sp))
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            if i == 0:
                item.setData(Qt.Checked, Qt.CheckStateRole)
            else:
                item.setData(Qt.Unchecked, Qt.CheckStateRole)
            self.model_3.setItem(i+1, 0, item)
        self.model_3.setItem(0,it0)
        self.cmbSp_3.setModel(self.model_3)
        self.cmbSp_3.setItemDelegate(ComboStyledItemDelegate())
        # 4
        self.model_4 = QtGui.QStandardItemModel(self.nsp, 1)# nsp rows, 1 col
        it0 = QtGui.QStandardItem('-- Select SP -- ')
        for i, sp  in enumerate(spList):
            item = QtGui.QStandardItem(str(sp))
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            if i == 0:
                item.setData(Qt.Checked, Qt.CheckStateRole)
            else:
                item.setData(Qt.Unchecked, Qt.CheckStateRole)
            self.model_4.setItem(i+1, 0, item)
        self.model_4.setItem(0,it0)
        self.cmbSp_4.setModel(self.model_4)
        self.cmbSp_4.setItemDelegate(ComboStyledItemDelegate())

    def loadZones(self):
        self.cmbZoneLayer_1.clear()
        self.cmbZoneLayer_2.clear()
        self.cmbZoneLayer_3.clear()
        self.cmbZoneLayer_4.clear()

        #if self.chkZone.isChecked():
##            zlist = []
##            for nn in self.layerNameList:
##                if '_zone' in nn:
##                    zlist.append(nn)
##
##            if "No" in self.cmbMultiplier_1.currentText():
##                self.cmbZoneLayer_1.addItems(zlist)
##            if "No" in self.cmbMultiplier_2.currentText():
##                self.cmbZoneLayer_2.addItems(zlist)
##            if "No" in self.cmbMultiplier_1.currentText():
##                self.cmbZoneLayer_3.addItems(zlist)
##            if "No" in self.cmbMultiplier_1.currentText():
##                self.cmbZoneLayer_4.addItems(zlist)
#
    def reloadZones1(self):
        # Row 1
        self.cmbZoneId_1.clear()
        if 'Yes' in self.cmbZoneOption_1.currentText() :
            # Retrieve
            zonelayer =  getVectorLayerByName(self.cmbZoneLayer_1.currentText())
            #
            try :
                zoneidlist = []
                request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
                for f in zonelayer.getFeatures(request):
                    zoneidlist.append(str(int(f['zone_lay_1'])))

                zoneidlist = set(zoneidlist)
                zoneidlist = list(zoneidlist)
                self.cmbZoneId_1.addItems(zoneidlist)

            except:
                return

    def reloadZones2(self):
        # Row 1
        self.cmbZoneId_2.clear()
        if 'Yes' in self.cmbZoneOption_2.currentText() :
            # Retrieve
            zonelayer =  getVectorLayerByName(self.cmbZoneLayer_2.currentText())
            #
            try :
                zoneidlist = []
                request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
                for f in zonelayer.getFeatures(request):
                    zoneidlist.append(str(int(f['zone_lay_1'])))

                zoneidlist = set(zoneidlist)
                zoneidlist = list(zoneidlist)
                self.cmbZoneId_2.addItems(zoneidlist)

            except:
                return

    def reloadZones3(self):
        # Row 1
        self.cmbZoneId_3.clear()
        if 'Yes' in self.cmbZoneOption_3.currentText() :
            # Retrieve
            zonelayer =  getVectorLayerByName(self.cmbZoneLayer_3.currentText())
            #
            try :
                zoneidlist = []
                request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
                for f in zonelayer.getFeatures(request):
                    zoneidlist.append(str(int(f['zone_lay_1'])))

                zoneidlist = set(zoneidlist)
                zoneidlist = list(zoneidlist)
                self.cmbZoneId_3.addItems(zoneidlist)

            except:
                return

    def reloadZones4(self):
        # Row 1
        self.cmbZoneId_4.clear()
        if 'Yes' in self.cmbZoneOption_4.currentText() :
            # Retrieve
            zonelayer =  getVectorLayerByName(self.cmbZoneLayer_4.currentText())
            #
            try :
                zoneidlist = []
                request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
                for f in zonelayer.getFeatures(request):
                    zoneidlist.append(str(int(f['zone_lay_1'])))

                zoneidlist = set(zoneidlist)
                zoneidlist = list(zoneidlist)
                self.cmbZoneId_4.addItems(zoneidlist)

            except:
                return

    def outFilecsv(self):
        (self.OutFilePath) = fileDialog(self)
        self.txtDirectory.setText(self.OutFilePath)
        # if self.OutFilePath is None or self.encoding is None:
            # rself):

##
    def createParams(self):
        # ------------ Load input data  ------------
        newName = self.lineNewLayerEdit.text()
        #
        # # Remark: pathfile from model table and number of stress periods (nsp) from time table
        (pathfile, nsp ) = getModelInfoByName(self.modelName)
        #
        # # Retrieve the information of the model and the name
        dbName = os.path.join(pathfile, self.modelName + '.sqlite')

        # creating/connecting SQL database object
        con = sqlite3.connect(dbName)
        con.enable_load_extension(True)
        cur = con.cursor()

        tableList = getTableNamesList(dbName)
        tableName = newName + "_params"

        if tableName in tableList:
            QMessageBox.warning(self, self.tr('Warning!'), self.tr('Yuo have already created a Parameters Table \n for model %s \n named "%s"! \n Please, change the name.' % (self.modelName,tableName )))
            pass
        #

        if self.csvBox.isChecked():
            # hack to convert the Qtext of the combobox in something like ',', else the upload in the db will fail
            column = repr(str(self.cmb_colsep.currentText()))

            # convert the decimal separator in a valid input for the uploadCSV function
            if self.cmb_decsep.currentText() == '.':
                decimal = 'POINT'
            else:
                decimal = 'COMMA'

            # hack to convert the Qtext of the combobox in something like ',', else loading in QGIS of the table will fail
            decimal2 = repr(self.cmb_decsep.currentText())

            # CSV table loader
            csvlayer = self.OutFilePath
            uri = QUrl.fromLocalFile(csvlayer)
            uri.addQueryItem("geomType","none")
            uri.addQueryItem("delimiter", column)
            uri.addQueryItem("decimal", decimal2)
            tableLayer = QgsVectorLayer(uri.toString(), tableName, "delimitedtext")

            uploadCSV(dbName, csvlayer, tableName, decimal_sep= decimal, column_sep= column, text_sep = 'DOUBLEQUOTE', charset = 'CP1250')

        #
        elif self.tableBox.isChecked():
            # create new table
            SQLstring = 'CREATE TABLE "%s" ("idparam" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "Name" varchar(20), "Package"  varchart(5) , "Type"  varchart(5), "StartValue" float, "Multiplier" varchart(5), "StressPeriod" int , "UseZones" varchart(5), "ZoneLayer" varchart(50),"ZoneId" int, "Adjustable" varchart(5), "Transform" varchart(5), "Constr" varchart(5), "Upper" float, "Lower" float, "PerturbAmt" float );'%tableName
            cur.execute(SQLstring)

            # If a parameter is linked to more than 1 SP, it is reapeted in rows as many as SPs count
            # INSERT
            # 1
            # Retrieve list of selected StressPeriods from SP combo
            splist = []
            i = 1
            while self.model.item(i):
                if self.model.item(i).checkState() == 2:
                    valore = self.model.item(i).data(0)
                    splist.append( int(valore) )
                i += 1
            #
            # Loop on the Stress Periods associated to this parameter
            for kper in splist :
                vls = []
                parname = self.txtName_1.text()
                vls.append(parname)
                package = self.cmbPackage_1.currentText()
                vls.append(package)
                partype = self.cmbType_1.currentText()
                vls.append(partype)
                startvalue = float(self.txtValue_1.text())
                vls.append(startvalue)
                multiplier = self.cmbMultiplier_1.currentText()
                vls.append(multiplier)
                vls.append(kper)
                usezone = self.cmbZoneOption_1.currentText()
                vls.append(usezone)
                if 'Yes' in self.cmbZoneOption_1.currentText():
                    zonelayer = self.cmbZoneLayer_1.currentText()
                    zoneid = int(self.cmbZoneId_1.currentText())
                else:
                    zonelayer = 'None'
                    zoneid = 0
                vls.append(zonelayer)
                vls.append(zoneid)
                adjustable = self.cmbAjust_1.currentText()
                vls.append(adjustable)
                transform = self.cmbTransform_1.currentText()
                vls.append(transform)
                constraint = self.cmbConst_1.currentText()
                vls.append(constraint)
                upper = float(self.txtUpper_1.text())
                vls.append(upper)
                lower = float(self.txtLower_1.text())
                vls.append(lower)
                perturbamt = float(self.txtPerturbAmt_1.text())
                vls.append(perturbamt)

                sqlinsert = 'INSERT INTO %s'%tableName
                sqlinsert_2 = ' ( Name ,  Package , Type , StartValue , Multiplier , StressPeriod , UseZones , ZoneLayer , ZoneId , Adjustable , Transform , Constr , Upper , Lower , PerturbAmt  ) VALUES (  ? , ? , ? , ? , ? , ? , ? , ? , ?  , ?  , ?  , ?  , ?  , ?  , ?  );'

                # from list to tuple
                vls = tuple(vls)

                cur.execute(sqlinsert + sqlinsert_2 , vls )

            # here we need a smarter way to loop over the 3 remaining rows......
            # 2
            # Retrieve list of selected StressPeriods from SP combo
            splist = []
            i = 1
            while self.model_2.item(i):
                if self.model_2.item(i).checkState() == 2:
                    valore = self.model_2.item(i).data(0)
                    splist.append( int(valore) )
                i += 1
            #
            parname = self.txtName_2.text()
            if parname != '':
                # Loop on the Stress Periods associated to this parameter
                for kper in splist :
                    vls = []
                    vls.append(parname)
                    package = self.cmbPackage_2.currentText()
                    vls.append(package)
                    partype = self.cmbType_2.currentText()
                    vls.append(partype)
                    startvalue = float(self.txtValue_2.text())
                    vls.append(startvalue)
                    multiplier = self.cmbMultiplier_2.currentText()
                    vls.append(multiplier)
                    vls.append(kper)
                    usezone = self.cmbZoneOption_2.currentText()
                    vls.append(usezone)
                    if 'Yes' in self.cmbZoneOption_2.currentText():
                        zonelayer = self.cmbZoneLayer_2.currentText()
                        zoneid = int(self.cmbZoneId_2.currentText())
                    else:
                        zonelayer = 'None'
                        zoneid = 0
                    vls.append(zonelayer)
                    vls.append(zoneid)
                    adjustable = self.cmbAjust_2.currentText()
                    vls.append(adjustable)
                    transform = self.cmbTransform_2.currentText()
                    vls.append(transform)
                    constraint = self.cmbConst_2.currentText()
                    vls.append(constraint)
                    upper = float(self.txtUpper_2.text())
                    vls.append(upper)
                    lower = float(self.txtLower_2.text())
                    vls.append(lower)
                    perturbamt = float(self.txtPerturbAmt_2.text())
                    vls.append(perturbamt)

                    # from list to tuple
                    vls = tuple(vls)

                    cur.execute(sqlinsert + sqlinsert_2 , vls )

            # 3
            # Retrieve list of selected StressPeriods from SP combo
            splist = []
            i = 1
            while self.model_3.item(i):
                if self.model_3.item(i).checkState() == 2:
                    valore = self.model_3.item(i).data(0)
                    splist.append( int(valore) )
                i += 1

            parname = self.txtName_3.text()
            if parname != '':
                # Loop on the Stress Periods associated to this parameter
                for kper in splist :
                    vls = []
                    vls.append(parname)
                    package = self.cmbPackage_3.currentText()
                    vls.append(package)
                    partype = self.cmbType_3.currentText()
                    vls.append(partype)
                    startvalue = float(self.txtValue_3.text())
                    vls.append(startvalue)
                    multiplier = self.cmbMultiplier_3.currentText()
                    vls.append(multiplier)
                    vls.append(kper)
                    usezone = self.cmbZoneOption_3.currentText()
                    vls.append(usezone)
                    if 'Yes' in self.cmbZoneOption_3.currentText():
                        zonelayer = self.cmbZoneLayer_3.currentText()
                        zoneid = int(self.cmbZoneId_3.currentText())
                    else:
                        zonelayer = 'None'
                        zoneid = 0
                    vls.append(zonelayer)
                    vls.append(zoneid)
                    adjustable = self.cmbAjust_3.currentText()
                    vls.append(adjustable)
                    transform = self.cmbTransform_3.currentText()
                    vls.append(transform)
                    constraint = self.cmbConst_3.currentText()
                    vls.append(constraint)
                    upper = float(self.txtUpper_3.text())
                    vls.append(upper)
                    lower = float(self.txtLower_3.text())
                    vls.append(lower)
                    perturbamt = float(self.txtPerturbAmt_3.text())
                    vls.append(perturbamt)

                    # from list to tuple
                    vls = tuple(vls)

                    cur.execute(sqlinsert + sqlinsert_2 , vls )
            # 4
            # Retrieve list of selected StressPeriods from SP combo
            splist = []
            i = 1
            while self.model_4.item(i):
                if self.model_4.item(i).checkState() == 2:
                    valore = self.model_4.item(i).data(0)
                    splist.append( int(valore) )
                i += 1
            #
            parname = self.txtName_4.text()
            if parname != '':
                for kper in splist :
                    vls = []
                    vls.append(parname)
                    package = self.cmbPackage_4.currentText()
                    vls.append(package)
                    partype = self.cmbType_4.currentText()
                    vls.append(partype)
                    startvalue = float(self.txtValue_4.text())
                    vls.append(startvalue)
                    multiplier = self.cmbMultiplier_4.currentText()
                    vls.append(multiplier)
                    vls.append(kper)
                    usezone = self.cmbZoneOption_4.currentText()
                    vls.append(usezone)
                    if 'Yes' in self.cmbZoneOption_4.currentText():
                        zonelayer = self.cmbZoneLayer_4.currentText()
                        zoneid = int(self.cmbZoneId_4.currentText())
                    else:
                        zonelayer = 'None'
                        zoneid = 0
                    vls.append(zonelayer)
                    vls.append(zoneid)
                    adjustable = self.cmbAjust_4.currentText()
                    vls.append(adjustable)
                    transform = self.cmbTransform_4.currentText()
                    vls.append(transform)
                    constraint = self.cmbConst_4.currentText()
                    vls.append(constraint)
                    upper = float(self.txtUpper_4.text())
                    vls.append(upper)
                    lower = float(self.txtLower_4.text())
                    vls.append(lower)
                    perturbamt = float(self.txtPerturbAmt_2.text())
                    vls.append(perturbamt)

                    # from list to tuple
                    vls = tuple(vls)

                    cur.execute(sqlinsert + sqlinsert_2 , vls )

            # Close SpatiaLiteDB
            cur.close()
            # Save the changes
            con.commit()
            # Close connection
            con.close()

        # load table (either if csv layer or filled in the table) in the TOC
        #if self.addCheck.isChecked():
        # load table (either if csv layer or filled in the table) in the TOC
        # connect to the DB and retireve all the information
        uri = QgsDataSourceURI()
        uri.setDatabase(dbName)
        schema = ''
        table = tableName
        geom_column = None
        uri.setDataSource(schema, table, geom_column)
        display_name = tableName
        tableLayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')

        # add the layer to the TOC
        QgsMapLayerRegistry.instance().addMapLayer(tableLayer)



        #Close the dialog window after the execution of the algorithm
        QDialog.reject(self)
