#! /usr/bin/env python
# -*- coding: utf-8 -*-
###########################################################################
#
# Eole NG
# Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
# Licence CeCill  http://www.cecill.info/licences/Licence_CeCILL_V2-fr.html
# eole@ac-dijon.fr
#
###########################################################################

"""

Importation automatique des fichiers AAF synchronisés via Zéphir :
- décompression des fichiers AAF
- lecture des responsables et des élèves
- écriture des responsables et des élèves
- lecture des personnels
- écriture des personnels (enseignants et administratifs)

"""

import sys
import tarfile
from os.path import join, dirname, basename, splitext
from scribe import entlogin
from scribe.parsing import aaf
from scribe.eoleldap import Ldap
from scribe.importation import log
from pyeole import lock
from scribe.eoletools import nscd_start, nscd_stop
from scribe.storage import init_store
from scribe.importation import writer, config

CATEGORY_PATTERN = {'eleves':'_Eleve_', 'personnels':'_PersEducNat_'}
OPTIONNAL_CATEGORY = {'responsables':'_PersRelEleve_'}

def extract(fname):
    """
    extraction des fichiers
    """
    tarball = tarfile.open(fname)
    tarball.extractall(config.TMP_DIR)
    return tarball.getnames()

def map_names(names):
    """
    associe les noms de fichiers aux catégories
    """
    result = {}
    for category, pat in CATEGORY_PATTERN.items():
        result[category] = filter_name(names, pat)
    # catégories optionnelles #1947
    for category, pat in OPTIONNAL_CATEGORY.items():
        try:
            result[category] = filter_name(names, pat)
        except:
            continue
    return result

def filter_name(tarfiles, name):
    """
    recherche des fichiers associés à une catégorie
    """
    fnames = [elt for elt in tarfiles if name in elt]
    assert len(fnames) == 1, "Unexpected lenght in %s" % str(fnames)
    return fnames[0]

def write_eleves(store):
    """
    écriture des élèves et des responsables
    """
    log.debuglog("Arrêt de nscd...", title=True)
    nscd_stop()
    connexion = Ldap()
    connexion.connect()
    writer.write_niveau(storage=store, connexion=connexion)
    writer.write_classe(storage=store, connexion=connexion)
    writer.write_option(storage=store, connexion=connexion)
    writer.write_eleve(storage=store, connexion=connexion)
    writer.write_responsable(storage=store, connexion=connexion)
    connexion.close()
    log.infolog("Affectation des identifiants uniques ENT...", title=True)
    entlogin.entlogin_eleves()
    entlogin.entlogin_responsables()
    log.debuglog("Démarrage de nscd...", title=True)
    nscd_start()

def write_personnels(store):
    """
    écriture des enseignants et personnels administratifs
    """
    log.debuglog("Arrêt de nscd...", title=True)
    nscd_stop()
    connexion = Ldap()
    connexion.connect()
    writer.verify_classe(storage=store, connexion=connexion)
    writer.write_matiere(storage=store, connexion=connexion)
    writer.verify_option(storage=store, connexion=connexion)
    writer.write_enseignant(storage=store, connexion=connexion)
    writer.write_service(storage=store, connexion=connexion)
    writer.write_administratif(storage=store, connexion=connexion)
    connexion.close()
    log.infolog("Affectation des identifiants uniques ENT...", title=True)
    entlogin.entlogin_enseignants()
    entlogin.entlogin_administratifs()
    log.debuglog("Démarrage de nscd...", title=True)
    nscd_start()

def run():
    """
    c'est parti !!!
    """
    if len(sys.argv) < 2:
        sys.exit(1)
    else:
        aaf_tar_fname = sys.argv[1]
    import_dir = dirname(aaf_tar_fname)
    lockname = '.%s.lock' % splitext(basename(aaf_tar_fname))[0]
    log.add_lock()
    try:
        if lock.check_lock(import_dir, lockname):
            lock.del_lock(import_dir, lockname)
        log.start_importation('auto')
        log.log.info("type d'import : synchro AAF")
        names = extract(aaf_tar_fname)
        category_files = map_names(names)
        store = init_store(config.DB_DIR)
        # gestion des élèves et des responsables
        if category_files.has_key('responsables'):
            aaf.parse_aaf_responsables(store, join(config.TMP_DIR, category_files['responsables']))
        aaf.parse_aaf_eleves(store, join(config.TMP_DIR, category_files['eleves']))
        write_eleves(store)
        # gestion des personnels
        aaf.parse_aaf_profs(store, join(config.TMP_DIR, category_files['personnels']))
        write_personnels(store)
        log.end_importation('auto')
        log.del_lock()
        sys.exit(0)
    except Exception, exc:
        import traceback
        traceback.print_exc()
        log.log.exception("Erreur lors de l'importation automatique AAF")
        lock.add_lock(import_dir, lockname)
        log.del_lock()
        sys.exit(1)

run()
