# -*- coding: utf-8 -*-
"""
/***************************************************************************
 Copie
                                 A QGIS plugin
 Permet la copie d'une table dans une base PostGis
                              -------------------
        begin                : 2015-04-13
        git sha              : $Format:%H$
        copyright            : (C) 2015 by Guillaume COSTES - CEN Rhône-Alpes
        email                : guillaume.costes@espaces-naturels.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""
#from PyQt4.QtCore import *
#from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
# Initialize Qt resources from file resources.py
import resources_rc
# Import the code for the dialog
from copie_dialog import CopieDialog
import os.path


class Copie:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'Copie_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Create the dialog (after translation) and keep reference
        self.dlg = CopieDialog()

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&Copie')
        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'Copie')
        self.toolbar.setObjectName(u'Copie')

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('Copie', message)


    def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/Copie/table_copie.png'
        self.add_action(
            icon_path,
            text=self.tr(u'Copie'),
            callback=self.run,
            parent=self.iface.mainWindow())


    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(
                self.tr(u'&Copie'),
                action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        del self.toolbar


    def run(self):
        """Run method that performs all the real work"""
        layer = self.iface.activeLayer()

        if layer == None :
            self.iface.messageBar().pushMessage(u"Vous devez sélectionner une table !", level=QgsMessageBar.WARNING, duration=5)

        else :
            # Récupération des sources de la couche active
            list_sources = layer.source().split(" ")
                # dbname
            source_db = [s for s in list_sources if "dbname" in s][0].split("'")[1]
                # schema
            source_schema = [s for s in list_sources if "table" in s][0].split('"')[1]
                # tablename
            source_tablename = [s for s in list_sources if "table" in s][0].split('"')[3]

            if source_db != 'sig4269':
                self.iface.messageBar().pushMessage(u"Un référentiel ne peut être copié, utilisez les filtres !", level=QgsMessageBar.CRITICAL, duration=10)

            else :
                import psycopg2
                
                config = "//100.100.100.100/bd_sig/z_QGIS/config.txt" # Chemin du fichier config        
                        # Fonction de lecture des lignes du fichier config      
                def readline(n):
                  with open(config, "r") as f:
                    for lineno, line in enumerate(f):
                      if lineno == n:
                        return line.strip() # Permet d'enlever les retours chariots
                        
                host = readline(10)             
                port = readline(12)             
                dbname = readline(14)               
                user = readline(16)             
                password = readline(18)
                
                con = psycopg2.connect("dbname="+ dbname + " user=" + user + " host=" + host + " password=" + password)
                cur = con.cursor()
                            # Creation de la liste des schemas de la base de donnees
                SQL = """WITH list_schema AS (
                SELECT catalog_name, schema_name
                    FROM information_schema.schemata
                    WHERE schema_name <> 'information_schema'
                    AND schema_name !~ E'^pg_'
                    ORDER BY schema_name
                    )

                SELECT string_agg(schema_name,',')
                    FROM list_schema
                    GROUP BY catalog_name"""

                cur.execute(SQL)

                list_brut = str(cur.next())

                list = list_brut [3:-3]
                listItems = list.split(",")

                con.close()
                
                self.dlg.schema.clear()
                self.dlg.schema.addItems(listItems)
                self.dlg.schema.setCurrentIndex(-1) # Pour ne pas commencer la liste au premier schema


                self.dlg.table_source.setText(source_schema + "." + source_tablename) # Affiche le nom de la table source
                # show the dialog
                self.dlg.show()
                # Run the dialog event loop
                result = self.dlg.exec_()
                # See if OK was pressed
                if result:
        #******************************debut script*********************************
                    ### config.txt
                    config = "//100.100.100.100/bd_sig/z_QGIS/config.txt" # Chemin du fichier config

                        # Fonction de lecture des lignes du fichier config
                    def readline(n):
                      with open(config, "r") as f:
                        for lineno, line in enumerate(f):
                          if lineno == n:
                            return line.strip() # Permet d'enlever les retours chariots

                        # Recuperation des donnees
                    host = readline(10)
                    port = readline(12)
                    dbname = readline(14)
                    user = readline(16)
                    password = readline(18)
                    
                    con = psycopg2.connect("dbname="+ dbname + " user=" + user + " host=" + host + " password=" + password)
                    cur = con.cursor()

                    # Récupération de la couche active
                    layer = self.iface.activeLayer()

                    # Récupération des sources de la couche active
                    list_sources = layer.source().split(" ")
                        # dbname
                    source_db = [s for s in list_sources if "dbname" in s][0].split("'")[1]
                        # schema
                    source_schema = [s for s in list_sources if "table" in s][0].split('"')[1]
                        # tablename
                    source_tablename = [s for s in list_sources if "table" in s][0].split('"')[3]

                    if self.dlg.schema.currentIndex() == -1 :
                        QMessageBox.warning(None, "Oups :", "Veuillez choisir un dossier de destination.")
                        return          
                    
                    schema = self.dlg.schema.currentText()

                    if self.dlg.table_destination.text() == '' :
                        QMessageBox.warning(None, "Oups :", "Veuillez choisir un nom de destination.")
                        return                     
                    
                    if  self.dlg.annee.text() == 'aaaa' or self.dlg.annee.text() == '':
                        tablename = schema + "_" + self.dlg.table_destination.text().lower()
                    else :
                        tablename = schema + "_" + self.dlg.table_destination.text().lower() + "_" + self.dlg.annee.text()

                    tablename_qgis = tablename[1:]  # Permet d'enlever le "_", ajouter a la premiere etape, dans qgis

                    geom = readline(6)        

                    if self.dlg.table_vide.isChecked() == 1 :
                        SQL_table = "CREATE TABLE " + schema + "." + tablename + " AS SELECT * FROM " + source_schema + "." + source_tablename + " LIMIT 0;"
                    else :
                        SQL_table = "CREATE TABLE " + schema + "." + tablename + " AS SELECT * FROM " + source_schema + "." + source_tablename


                    SQL_pkey = "ALTER TABLE " + schema + "." + tablename + " ADD CONSTRAINT " + tablename + "_pkey" + " PRIMARY KEY (gid)"
                    SQL_sequence_01 = "CREATE SEQUENCE " + schema + "." + tablename + "_gid_seq" + " INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1;"
                    SQL_sequence_02 = "ALTER TABLE " + schema + "." + tablename + " ALTER COLUMN gid SET DEFAULT nextval(\'" + schema + "." + tablename + "_gid_seq\'::regclass);" 
                    SQL_sequence_03 = "SELECT setval(\'" + schema + "." + tablename + "_gid_seq\'::regclass, (SELECT max(gid) AS max_gid FROM " + schema + "." + tablename + "));"
                    SQL_sequence_04 = "ALTER SEQUENCE " + schema + "." + tablename + "_gid_seq" + " OWNED BY " + schema + "." + tablename + ".gid;"

                    SQL_trigger_area_m2 = "CREATE TRIGGER area_m2" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.area_m2();"
                    SQL_trigger_area_ha = "CREATE TRIGGER area_ha" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.area_ha();"               
                    SQL_trigger_length_m = "CREATE TRIGGER length_m" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.length_m();"
                    SQL_trigger_length_km = "CREATE TRIGGER length_km" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.length_km();"             
                    SQL_trigger_coordonnees = "CREATE TRIGGER coordonnees" + tablename + " BEFORE INSERT OR UPDATE ON " + schema + "." + tablename + " FOR EACH ROW EXECUTE PROCEDURE ref.coordonnees();"               

                    cur.execute(SQL_table)
                    cur.execute(SQL_pkey)
                    cur.execute(SQL_sequence_01)
                    cur.execute(SQL_sequence_02)
                    cur.execute(SQL_sequence_03)
                    cur.execute(SQL_sequence_04)

                    if layer.wkbType() == QGis.WKBPoint :
                        cur.execute(SQL_trigger_coordonnees)

                    if layer.wkbType() == QGis.WKBMultiLineString :
                        cur.execute(SQL_trigger_length_m)
                        cur.execute(SQL_trigger_length_km)                  

                    if layer.wkbType() == QGis.WKBMultiPolygon :
                        cur.execute(SQL_trigger_area_m2)
                        cur.execute(SQL_trigger_area_ha)
                        
                    con.commit()                
               
                    ### Affichage de la table
                    uri = QgsDataSourceURI()
                      # set host name, port, database name, username and password
                    uri.setConnection(host ,port ,dbname ,user ,password)
                      # set database schema, table name, geometry column and optionaly subset (WHERE clause)
                    uri.setDataSource(schema, tablename, geom)

                    layer = self.iface.addVectorLayer(uri.uri(), tablename_qgis, "postgres")
                        
                    con.commit()
                    con.close()

                    self.iface.messageBar().pushMessage("Table \"" + source_schema + "." + source_tablename + u"\" copiée dans \"" + schema + "." + tablename + "\"." , level=QgsMessageBar.INFO, duration=10)
                    pass
