# -*- 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
#
# fonctions xmlrpc pour la gestion des dictionnaires creole
#
###########################################################################
"""module de gestion des dictionnaires Creole
"""
from zephir.backend.db_utils import *
from zephir.backend import config
from zephir.backend.config import u, log
from zephir.backend.xmlrpceole import XMLRPCEole as XMLRPC
import traceback

class RPCDicos(XMLRPC):
    """serveur XMLRPC zephir pour la gestion des dictionnaires Creole
    """

    def __init__(self, parent):
        self.parent = parent
        XMLRPC.__init__(self)

    ###########################################
    # gestion du pool de dictionnaires/paquets

    def _check_resource_perms(self, cred_user, eole_version, dict_name):
        """vérifie qu'on a l'autorisation de modifier les ressources utilisant un dictionnaire local
        """
        dict_resources = self.parent.dictpool.get_dict_resources(eole_version, 'local', dict_name)
        # en cas de dictionnaire déjà utilisé par un module/variante,
        # on vérifie les restrictions d'accès
        if dict_resources['module']:
            for id_mod in dict_resources['module']:
                self.parent.s_pool.check_mod_credential(cred_user, id_mod)
        elif dict_resources['variante']:
            for id_var in dict_resources['variante']:
                self.parent.s_pool.check_var_credential(cred_user, id_var)
        # serveurs: vérification des droits d'accès
        elif dict_resources['serveur']:
            allowed_s = set([int(serv) for serv in self.parent.s_pool.get_allowed_servers(cred_user)])
            # on vérifie qu'on a bien accès à tous les serveurs affectés
            assert set(dict_resources['serveur']).issubset(allowed_s), "Ce dictionnaire affecte un serveur auquel vous n'avez pas accès"

    def xmlrpc_get_dict(self, cred_user, eole_version, type_dict, dict_name, paq_name=""):
        """renvoie le contenu d'un dictionnaire du pool
        paq_name: nom du paquet pour les dictionnaires non isolés
        """
        try:
            result = self.parent.dictpool.get_dict(eole_version, type_dict, dict_name, paq_name)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(result)

    def xmlrpc_add_dict(self, cred_user, eole_version, dict_name, content, paq_name=""):
        """ajoute ou met à jour un dictionnaire dans le dépot.
        paq_name: met le dictionnaire dans un répertoire de paquet
        """
        try:
            self._check_resource_perms(cred_user, eole_version, paq_name or dict_name)
            # vérification passées, on ajoute/met à jour le dictionnaire
            assert dict_name.endswith('.xml'), "Le dictionnaire doit être au format .xml"
            result = self.parent.dictpool.add_dict(eole_version, dict_name, content, paq_name)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(result)

    def xmlrpc_remove_dict(self, cred_user, eole_version, dict_name, paq_name=""):
        """supprime un dictionnaire/paquet du dépot (et les liens associés)
        """
        try:
            self._check_resource_perms(cred_user, eole_version, paq_name or dict_name)
            # vérification passées, on supprime le dictionnaire
            result = self.parent.dictpool.remove_dict(eole_version, dict_name, paq_name)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(result)

    def xmlrpc_get_dict_resources(self, cred_user, eole_version, dict_type, dict_name):
        """renvoie l'ensemble des ressources utilisant un dictionnaire ou paquet
        """
        try:
            resources = self.parent.dictpool.get_dict_resources(eole_version, dict_type, dict_name)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(resources)

    def xmlrpc_get_dict_links(self, cred_user, eole_version, dict_type, dict_name):
        """renvoie l'ensemble des liens pointant sur un dictionnaire ou paquet
        """
        try:
            liste_dicts = self.parent.dictpool.get_dict_links(eole_version, dict_type, dict_name)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(liste_dicts)

    def xmlrpc_get_paq_dict(self, cred_user, eole_version, liste_paqs):
        """renvoie la liste des dictionnaires d'un paquet
        """
        try:
            liste_dicts = self.parent.dictpool.get_paq_dict(eole_version, liste_paqs)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(liste_dicts)

    def xmlrpc_list_available(self, cred_user, eole_version, type_paq=None):
        """renvoie la liste des dictionnaires disponibles dans le pool pour une distribution eole
        type_paq : permet de limiter le résultat aux paquets eole ou locaux
        """
        # types de données renvoyés par défaut
        types_paq = ('eole', 'local')
        if type_paq and type_paq in types_paq:
            types_paq = [type_paq]
        dict_res = {}
        for type_paq in types_paq:
            dict_res[type_paq] = {}
            dict_res[type_paq]['dicos'] = self.parent.dictpool.dicos.get(eole_version,{}).get(type_paq, {})
            dict_res[type_paq]['paqs'] = self.parent.dictpool.paqs.get(eole_version,{}).get(type_paq, {})
        return 1, u(dict_res)

    def xmlrpc_update_dicts(self, cred_user, module_version, dict_type="local"):
        """force une vérification des dictionnaires disponibles pour une distribution
        module_version : version de la distribution à vérifier
        dict_type: dictionnaires 'eole' ou 'locaux'
        """
        try:
            assert int(module_version) in self.parent.dictpool.eole_versions
        except:
            return 0, u("version de distribution non gérée")
        if dict_type not in ('eole', 'local'):
            return 0, u("le type de dictionnaire doit être 'eole' ou 'local'")
        try:
            self.parent.dictpool.update_dicts(int(module_version), dict_type)
        except Exception as e:
            traceback.print_exc()
            return 0, False
        return 1, True

    ###############################################
    # gestion des associations au niveau module

    def xmlrpc_managed_modules(self, cred_user):
        """renvoie la liste des version de distribution comportant
        des modules gérés avec le pool (et les ids des modules en question)
        """
        res = {}
        for id_mod, data in list(self.parent.dictpool.modules.items()):
            libelle, version = data
            if str(version) not in res:
                res[str(version)] = []
            res[str(version)].append(id_mod)
        return 1, res

    def xmlrpc_check_module(self, cred_user, id_module):
        """renvoie True si un module est géré par le pool de dictionnaire, False sinon
        (pour compatibilité, toujours vrai sur Zéphir 2.6)
        """
        return 1, True

    def xmlrpc_list_module(self, cred_user, id_module, full_path=True):
        """liste les dictionnaires associés à un module
        """
        try:
            self.parent.s_pool.check_mod_credential(cred_user, int(id_module))
            list_dicts = self.parent.dictpool.list_module(id_module, full_path)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(list_dicts)

    def xmlrpc_add_module(self, cred_user, id_module, dict_type, dict_path):
        """associe un dictionnaire/paquet à un module
        """
        try:
            self.parent.s_pool.check_mod_credential(cred_user, int(id_module))
            self.parent.dictpool.add_module_dict(id_module, dict_type, dict_path)
        except Exception as e:
            return 0, u(str(e))
        return 1, "OK"

    def xmlrpc_del_module(self, cred_user, id_module, dict_type, dict_path):
        """supprime l'association entre un module et un dictionnaire/paquet
        """
        try:
            self.parent.s_pool.check_mod_credential(cred_user, int(id_module))
            self.parent.dictpool.del_module_dict(id_module, dict_type, dict_path)
        except Exception as e:
            return 0, u(str(e))
        return 1, "OK"

    def xmlrpc_get_module_defaults(self, cred_user, id_module, full_path=True):
        """renvoie la liste des paquets par défaut d'un module
        (basé sur le fichier de description du module)
        """
        try:
            self.parent.s_pool.check_mod_credential(cred_user, int(id_module))
            liste_dicts = self.parent.dictpool.get_module_defaults(id_module, full_path)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(liste_dicts)

    ###############################################
    # gestion des associations au niveau variante

    def xmlrpc_list_variante(self, cred_user, id_variante, full_path=True):
        """liste les dictionnaires associés à une variante
        """
        try:
            self.parent.s_pool.check_var_credential(cred_user, int(id_variante))
            list_dicts = self.parent.dictpool.list_variante(id_variante, full_path)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(list_dicts)


    def xmlrpc_add_variante(self, cred_user, id_variante, dict_type, dict_path, pass_var=""):
        """associe un paquet/dictionnaire à une variante
        """
        try:
            assert self.parent.dictpool.check_passvar(id_variante, cred_user, pass_var) == True
            self.parent.s_pool.check_var_credential(cred_user, int(id_variante))
            self.parent.dictpool.add_variante_dict(id_variante, dict_type, dict_path)
        except Exception as e:
            return 0, u(str(e))
        return 1, "OK"

    def xmlrpc_del_variante(self, cred_user, id_variante, dict_type, dict_path, pass_var=""):
        """supprime l'association entre un module et un dictionnaire/paquet
        """
        try:
            assert self.parent.dictpool.check_passvar(id_variante, cred_user, pass_var) == True
            self.parent.s_pool.check_var_credential(cred_user, int(id_variante))
            self.parent.dictpool.del_variante_dict(id_variante, dict_type, dict_path)
        except Exception as e:
            traceback.print_exc()
            return 0, u(str(e))
        return 1, "OK"

    ###############################################
    # gestion des associations au niveau serveur

    def xmlrpc_check_serveur(self, cred_user, id_serveur):
        """renvoie True si le module d'un serveur est géré par le pool de dictionnaire,
        (pour compatibilité, toujours vrai sur Zéphir 2.6)
        """
        return 1, True

    def xmlrpc_list_serveur(self, cred_user, id_serveur):
        """liste les dictionnaires associés à un serveur
        """
        try:
            self.parent.s_pool.check_serv_credential(cred_user, int(id_serveur))
            list_dicts = self.parent.dictpool.list_serveur(id_serveur)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(list_dicts)

    def xmlrpc_add_serveur(self, cred_user, id_serveur, dict_type, dict_path):
        """associe un dictionnaire/paquet à un serveur
        """
        try:
            self.parent.s_pool.check_serv_credential(cred_user, int(id_serveur))
            self.parent.dictpool.add_serveur_dict(id_serveur, dict_type, dict_path)
        except Exception as e:
            return 0, u(str(e))
        return 1, "OK"

    def xmlrpc_del_serveur(self, cred_user, id_serveur, dict_type, dict_path):
        """supprime l'association entre un serveur et un dictionnaire/paquet
        """
        try:
            self.parent.s_pool.check_serv_credential(cred_user, int(id_serveur))
            self.parent.dictpool.del_serveur_dict(id_serveur, dict_type, dict_path)
        except Exception as e:
            return 0, u(str(e))
        return 1, "OK"

    def xmlrpc_list_local_serveur(self, cred_user, id_serveur):
        """renvoie la liste des dictionnaires et paquets devant être
        mis en place sur un serveur
        """
        try:
            self.parent.s_pool.check_serv_credential(cred_user, int(id_serveur))
            liste_dicts = self.parent.dictpool.list_local_serveur(id_serveur)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(liste_dicts)

    def xmlrpc_check_inactive(self, cred_user, serveurs):
        """indique si des dictionnaires non activés sont détectés sur un
        ensemble de serveurs.
        serveurs : liste d'identifiants de serveurs
        renvoie True si c'est le cas, False sinon (sans détail supplémentaire)
        """
        try:
            if type(serveurs) != list:
                # id de serveur unique
                serveurs = [serveurs]
            for id_s in serveurs:
                if self.parent.dictpool.get_inactive_packages(int(id_s)):
                    # on s'arrête au premier cas trouvé
                    return 1, True
        except Exception as e:
            return 0, u(str(e))
        return 1, False

    def xmlrpc_get_inactive(self, cred_user, id_serveur):
        """renvoie la liste des paquets de dictionnaires installés
        sur un serveur mais non activés sur Zéphir
        id_serveur : identifiant d'un serveur
        """
        try:
            self.parent.s_pool.check_serv_credential(cred_user, int(id_serveur))
            packages = self.parent.dictpool.get_inactive_packages(id_serveur)
        except Exception as e:
            return 0, u(str(e))
        return 1, u(packages)

#    # fonctions internes ?????
#    update_module(id_module)
#    update_variante(id_variante, id_mod = None)
#    get_var_mod(id_variante)
#    update_serveur(id_serveur)
#    get_serveur(id_serveur)
#    reset_modules(self)
#    update_data(self)
#    check_dict(eole_version, dict_type, dict_name)
#    check_type_res(res_type)
#    get_link_path(eole_version, id_res, type_res, dict_type, dict_name)

