# -*- 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 __future__ import absolute_import
#from PyQt4.QtCore import *
#from PyQt4.QtGui import *
from qgis.PyQt.QtCore import QSettings
from qgis.PyQt.QtWidgets import QAction, QMenu, QDialog, QMessageBox
from qgis.PyQt.QtGui import QIcon
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from qgis.core import QgsDataSourceUri
from builtins import str
from builtins import object
from qgis.core import *
from qgis.gui import *
# Initialize Qt resources from file resources.py
from . import resources_rc
# Import the code for the dialog
from .copie_dialog import CopieDialog
import os.path
from .PythonSQL import *
import psycopg2
import psycopg2.extras
import base64
#import socket
import os
#import sys

class Copie(object):
    """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)
            self.iface.messageBar().pushMessage("Ooops", u"Vous devez sélectionner une table !", level=Qgis.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 != sigdb:
                #self.iface.messageBar().pushMessage(u"Un référentiel ne peut être copié, utilisez les filtres !", level=QgsMessageBar.CRITICAL, duration=10)
                self.iface.messageBar().pushMessage("Ooops", u"Vous ne pouvez copier des couches que dans sigXX", level=Qgis.Critical, duration=5)

            else :

                first_conn = psycopg2.connect("host=" + host + " port=" + port + " dbname="+dbname+" user=first_cnx password=" + password)
                first_cur = first_conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
                first_cur.execute("SELECT mdp_w, login_w FROM pg_catalog.pg_user t1, admin_sig.vm_users_sig t2 WHERE t2.oid = t1.usesysid AND (login_w = '" + os_user + "' OR login_w = '" + os_user + "')")
                res_ident = first_cur.fetchone()
                mdp = base64.b64decode(str(res_ident[0])).decode('utf-8')
                user = res_ident[1]
                con = psycopg2.connect("host=" + host + " port=" + port + " dbname="+dbname+" user=" + user + " password=" + mdp)
                cur = con.cursor(cursor_factory = psycopg2.extras.DictCursor)
                first_conn.close()

                            # 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(next(cur))

                list = list_brut [2:-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*********************************


                    first_conn = psycopg2.connect("host=" + host + " port=" + port + " dbname="+dbname+" user=first_cnx password=" + password)
                    first_cur = first_conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
                    first_cur.execute("SELECT mdp_w, login_w FROM pg_catalog.pg_user t1, admin_sig.vm_users_sig t2 WHERE t2.oid = t1.usesysid AND (login_w = '" + os_user + "' OR login_w = '" + os_user + "')")
                    res_ident = first_cur.fetchone()
                    mdp = base64.b64decode(str(res_ident[0])).decode('utf-8')
                    user = res_ident[1]
                    con = psycopg2.connect("host=" + host + " port=" + port + " dbname="+dbname+" user=" + user + " password=" + mdp)
                    cur = con.cursor(cursor_factory = psycopg2.extras.DictCursor)
                    first_conn.close()
                    # 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

                    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() == QgsWkbTypes.PointGeometry :
                        cur.execute(SQL_trigger_coordonnees)

                    if layer.wkbType() == QgsWkbTypes.LineGeometry :
                        cur.execute(SQL_trigger_length_m)
                        cur.execute(SQL_trigger_length_km)                  

                    if layer.wkbType() == QgsWkbTypes.PolygonGeometry :
                        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 ,mdp)
                      # 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)
                    self.iface.messageBar().pushMessage("Bravo!", "Table \"" + source_schema + "." + source_tablename + u"\" copiée dans \"" + schema + "." + tablename + "\".", level=Qgis.Success, duration=5)
                    pass
