# -*- 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
#
# aaf_rpc.py
#
# fonctions xmlrpc pour la gestion des fichier d'import AAF
#
###########################################################################
"""module de gestion des fichiers d'import AAF
"""

from zephir.backend.config import AAF_DIR
from zephir.backend.lib_backend import cx_pool
from twisted.internet.utils import getProcessValue
from twisted.internet import defer
import os

class AAF:
    """gestion des fichiers d'import AAF
    """

    def __init__(self):
        if not os.path.isdir(AAF_DIR):
            os.makedirs(AAF_DIR)

    def add_file(self, nom_fichier, id_serveur):
        """ajoute un fichier à surveiller
        """
        query = """insert into import_aaf (id_serveur,fichier) values (%s,%s)"""
        cursor = cx_pool.create()
        cursor.execute(query, (id_serveur, nom_fichier))
        cx_pool.commit(cursor)

    def del_file(self, nom_fichier):
        """supprime un fichier de la liste des fichiers à surveiller
        """
        query = """delete from import_aaf where fichier=%s"""
        cursor = cx_pool.create()
        cursor.execute(query, (nom_fichier,))
        cx_pool.commit(cursor)
        # si le fichier existe dans le répertoire, on le supprime
        if os.path.isfile(os.path.join(AAF_DIR, nom_fichier)):
            os.unlink(os.path.join(AAF_DIR, nom_fichier))
        if os.path.isfile(os.path.join(AAF_DIR, '%s.sha256' % nom_fichier)):
            os.unlink(os.path.join(AAF_DIR, '%s.sha256' % nom_fichier))

    def get_serveur(self, nom_fichier):
        """indique à quel serveur un fichier est attribué
        """
        query = """select id_serveur from import_aaf where fichier=%s"""
        cursor = cx_pool.create()
        cursor.execute(query, (nom_fichier,))
        serveur = cursor.fetchone()
        cx_pool.close(cursor)
        if serveur is not None:
            return serveur[0]
        raise ValueError("""pas de serveur associé à ce fichier""")

    def list_files(self, id_serveur):
        """renvoie la liste des fichiers surveillés
        """
        query = """select fichier from import_aaf where id_serveur=%s"""
        cursor = cx_pool.create()
        cursor.execute(query, (id_serveur,))
        fichiers = cursor.fetchall()
        cx_pool.close(cursor)
        return [fichier[0] for fichier in fichiers]

    def update_hash(self, nom_fichier, hash_data):
        """met à jour le hash d'un fichier
        """
        # stockage de la somme md5
        query = """update import_aaf set hash=%s where fichier=%s"""
        cursor = cx_pool.create()
        cursor.execute(query, (hash_data, nom_fichier))
        cx_pool.commit(cursor)

    def check_hash(self, nom_fichier):
        """vérifie si un fichier a été modifié
        renvoie True si le fichier est modifié, False sinon
        """
        # récupération du dernier hash enregistré
        query = """select hash from import_aaf where fichier = %s"""
        cursor = cx_pool.create()
        cursor.execute(query, (nom_fichier,))
        hash_data = cursor.fetchone()
        cx_pool.close(cursor)
        if hash_data and hash_data[0] is not None:
            # valeur trouvée, on compare avec le fichier actuel
            f_hash = open(os.path.join(AAF_DIR, '%s.sha256' % nom_fichier), 'w')
            f_hash.write("%s *%s" % (hash_data[0].strip(), nom_fichier))
            f_hash.close()
            cmd_sha = getProcessValue("/usr/bin/sha256sum",
                                      args = ['-c', '%s.sha256' % nom_fichier],
                                      path = AAF_DIR,
                                      env = {'LC_ALL': 'C'})
            return cmd_sha.addBoth(self._check_sha_verify)
        # pas encore de md5 enregistré, on considère le fichier modifié
        return defer.succeed(True)

    def _check_sha_verify(self, result):
        """traitement du retour de la vérification de checksum
        """
        if result == 0:
            # pas de changement
            return False
        else:
            return True
