# -*- coding: UTF-8 -*-
###########################################################################
# Eole NG - 2007
# Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
# Licence CeCill  cf /root/LicenceEole.txt
# eole@ac-dijon.fr
#
# erreur.py
#
# Gère les exceptions liées au backend + utilitaires de conversion unicode
#
###########################################################################
"""Gère les exceptions

La fonction backend est là pour tansformer les return_code xml-rpc en levée d'exceptions

codes d'erreurs renvoyés par postgres:

libpq.OperationalError  (ex : ERROR:  Bad date external representation 'test')
libpq.IntegrityError    (ex : ERROR:  $1 referential integrity violation - key referenced from variantes not found in modules)

"""
from zephir.web.config import charset
from twisted.python import log
from html import escape

BACKEND_EXCEPTIONS = ['libpq.OperationalError','libpq.IntegrityError']

class BackendError(Exception):
    """Gère les erreurs provenant du backend xml-rpc
    """

    def __init__(self, msg=None):
        """Définition du message d'erreur
        """
        txt = """<p><span id="alerte">Erreur provenant du backend XML-RPC</span></p>
        <a href="javascript:history.back()">Retour</a><br/></p>"""
        if msg :
            txt2 = """<p><font size=-1><b>Détail</b><i> : %s </i></font></p>""" % str(msg)
            self.msg = txt + txt2
        else :
            self.msg = txt

    def __str__(self):
        return self.msg

class DatabaseError(Exception):
    """Différencie une erreur backend simple
    d'un pb d'intégrité référentielle
    """
    def __init__(self, msg=None):
        txt = """Interdiction due à un problème d'intégrité référentielle dans la base de données
        """
        if msg:
            txt2 = """, dans la table : <b>""" + msg + "</b>"
            self.msg = txt + txt2
        else :
            self.msg = "<p>" + txt + "</p>"

    def __str__(self):
        return self.msg

class FrontendError(Exception):
    """Gère les erreurs provenant du frontend web
    """
    def __init__(self, msg=None):
        """msg est à prioris un paramètre de request.args inexistant ou vide
        """
        txt = """<p><span id="alerte">Erreur provenant du frontend web, certains champs sont mal renseignés ou vides</span></p>"""
        retour = """<p><a href="javascript:history.back()">Retour à la liste des serveurs sélectionnés</a><br/></p>"""
        if msg :
            txt2 = """<p><b>Détail</b> : le paramètre %s n'est pas renseigné</p>""" % msg
            self.msg = txt + txt2 + retour
        else :
            self.msg = txt + retour

    def __str__(self):
        return str(self.msg)

def convert(objet):
    """Transforme les objets unicode contenus dans un objet en chaines
    """
    if type(objet) == list:
        l = []
        for item in objet:
            l.append(convert(item))
        return l
    if type(objet) == tuple:
        l = []
        for item in objet:
            l.append(convert(item))
        return l
    if type(objet) == dict:
        dico={}
        for cle in list(objet.keys()):
            dico[cle] = convert(objet[cle])
        return dico
    if type(objet) == str:
        return escape(objet)
    return objet

def u(objet):
    if type(objet) == tuple:
        l = []
        for item in objet:
            l.append(u(item))
        return l
    if type(objet) == list:
        l = []
        for item in objet:
            l.append(u(item))
        return l
    if type(objet) == dict:
        dico={}
        for cle in list(objet.keys()):
            dico[cle] = u(objet[cle])
        return dico
    return objet

def backend(liste_backend, log_error=True):
    """Récupère les codes et les messages d'erreur système
    log_error: ne logge pas le message en cas de code de retour 0
               (à utiliser dans le cas où on attend ce retour)
    """
    # premier terme de la liste
    return_code = liste_backend[0]
    # le contenu à récupérer... si tout va bien
    # sinon, c'est une exception ou un message d'erreur
    retour = liste_backend[1]
    try:
        assert liste_backend[2]
        database_msg = convert(liste_backend[2])
    except:
        database_msg = ""

    if not return_code :
        # quelque chose close
        if retour in BACKEND_EXCEPTIONS :
            # extrait la table concernée du message d'erreur
            if log_error:
                print(('erreur base de données : %s' % database_msg))
            database_msg = database_msg.split("from")[1].split()[0]
            raise DatabaseError(database_msg)
        else:
            # tout va mal
            if log_error:
                print(('erreur backend xmlrpc : %s' % convert(retour)))
            raise BackendError(convert(retour))
    else:
        # tout va bien
        retour = convert(retour)
        return retour

def get_groupe_vars(request):
    groupe_vars = {}
    # recherche des critères de variables définis
    for arg_name, arg_value in request.args.items():
        arg_name = arg_name.decode()
        if arg_name.startswith('var_') and arg_value[0].decode() != "":
            # recherche des différents paramètres pour cette variable
            varnegate = False
            varoptional = False
            varname = arg_value[0].decode()
            varvalue = request.args[('val_%s' % arg_name).encode()][0].decode()
            varnegate = request.args[('negate_%s' % arg_name).encode()][0].decode()
            groupe_vars[arg_name] = (varname,varvalue,bool(int(varnegate)))
    return groupe_vars

def pretty_select_module(modules):
    """
    jolie présentation pour les options des "select" sur les modules
    """
    current = ''
    l = []
    for module in modules :
        version = module['libelle'].split('-')[-1]
        if version.startswith('1.'):
            version = '1.x'
        if version != current:
            if current != '':
                l.append('</OPTGROUP>')
            s = """<OPTGROUP LABEL="Eole-%s">""" % version
            current = version
            l.append(s)
        s = """<OPTION VALUE="%s">%s</OPTION>""" % (module['id'], module['libelle'])
        l.append(s)
    if current != '':
        l.append('</OPTGROUP>')
    return "\n".join(l)
