#!/usr/bin/env python2
# -*- coding:utf8 -*-

from optparse import OptionParser
from os import path, makedirs
from sys import exit, argv
#from samba.samdb import SamDB
#from samba.auth import system_session
#from samba import getopt
#import ldb
from shutil import move, rmtree
from os import listdir
from configobj import ConfigObj

from creole.client import CreoleClient
from scribe.eleves import Eleve
from scribe.enseignants import Enseignant
from scribe.administratifs import Administratif
from scribe.eolegroup import Group
from scribe import eoleshare  # import Share
from scribe.ldapconf import USERS_DN, SMB_SERVEUR, GROUP_PATH, CLASS_PATH, OPT_PATH, AD_HOME_PATH, RECYCLAGE_PATH, SHARE_FILTER
from fichier.quota import get_quota
from pyeole.process import system_code
from datetime import datetime


conffile = '/etc/synchro_aaf.conf'
config = ConfigObj(conffile)
QUOTA_STUDENT = int(config.get('quota_student', 0))
QUOTA_STUDENT_HARD = int(config.get('quota_student_hard', 0))
QUOTA_TEACHER = int(config.get('quota_teacher', 0))
QUOTA_TEACHER_HARD = int(config.get('quota_teacher_hard', 0))
QUOTA_ADMINISTRATIVE = int(config.get('quota_administrative', 0))
QUOTA_ADMINISTRATIVE_HARD = int(config.get('quota_administrative_hard', 0))


exit_code = 0
if '--debug' in argv:
    DEBUG = True
else:
    DEBUG = False


def set_quota(login,
              quota,
              hard_quota,
              ):
    cmd = ['/usr/sbin/quotatool', '-b',
           '-q', '%dM' % quota,
           '-l', '%dM' % hard_quota,
           '-u', login, '/home']
    return system_code(cmd, container='fichier')


if DEBUG:
    print('debug de la synchronisation')
etab_id_variable = 'numero_etab'
etab_id = '(rne={})'.format(CreoleClient().get_creole(etab_id_variable))
nom_domaine_machine = CreoleClient().get_creole('nom_domaine_machine')
base_dn = CreoleClient().get_creole('base_dn')
meta_eleve = Eleve()
meta_enseignant = Enseignant()
meta_administratif = Administratif()
meta_group = Group()
eoleshare.SHARE_FILTER = '(&' + SHARE_FILTER + etab_id + ')'
meta_share = eoleshare.Share()

parse = OptionParser()
#lp = getopt.SambaOptions(parse).get_loadparm()
#creds = getopt.CredentialsOptions(parse).get_credentials(lp)
#samdb = SamDB(session_info=system_session(), credentials=creds, lp=lp)
meta_eleve.ldap_admin.connect()
search = meta_eleve.ldap_admin._search

cquery = "(&(objectClass=classe){})".format(etab_id)
local_classes = [str(classe[1]['cn'][0]) for classe in search(cquery)]

#query = "(homedirectory=*{}*)".format(nom_domaine_machine)
#local_users = search(query)
gquery = "(&(type=Etablissement){})".format(etab_id)
local_users = []
for group in search(gquery):
    local_users.extend(search("(memberOf={})".format(group[0])))
local_etab_groups = [str(option[1]['cn'][0]) for option in search(gquery)]

oquery = "(&(objectClass=eolegroupe)(type=option){})".format(etab_id)
local_options = [str(option[1]['cn'][0]) for option in search(oquery)]

equery = "(&(objectClass=eolegroupe)(type=equipe){})".format(etab_id)
local_equipes = [str(equipe[1]['cn'][0]) for equipe in search(equery)]

#query = "(&(objectClass=eolegroupe){})".format(etab_id)
#local_groups = search(query)
#print(local_groups)

#query = "(&(objectClass=sambaFileShare)(sambaShareURI=*{}*))".format(nom_domaine_machine)
#local_shares = search(query)

meta_eleve.ldap_admin.close()

if DEBUG:
    print(' * classes local {}'.format(cquery))
for name in local_classes:
    if DEBUG:
        print('  - {}'.format(name))
    meta_share._make_dirs(name, path.join(GROUP_PATH, name), 'classe')
if path.isdir(CLASS_PATH):
    for classe in set(listdir(CLASS_PATH)) - set(local_classes):
        print("Suppression de l'ancienne classe {}".format(classe))
        rmtree(path.join(CLASS_PATH, classe))

if DEBUG:
    print(' * options local {}'.format(oquery))
for name in local_options:
    if DEBUG:
        print('  - {}'.format(name))
    meta_share._make_dirs(name, path.join(GROUP_PATH, name), 'option')
if path.isdir(OPT_PATH):
    for option in set(listdir(OPT_PATH)) - set(local_options):
        print("Suppression de l'ancienne option {}".format(option))
        rmtree(path.join(OPT_PATH, option))

if DEBUG:
    print(' * equipes local {}'.format(equery))
for name in local_equipes:
    if DEBUG:
        print('  - {}'.format(name))
    meta_share._make_dirs(name, path.join(GROUP_PATH, name), 'rw')

if DEBUG:
    print(' * groupes local {}'.format(gquery))
for name in local_etab_groups:
    if DEBUG:
        print('  - {}'.format(name))
    meta_share._make_dirs(name, path.join(GROUP_PATH, name), 'rw')

if path.isdir(GROUP_PATH):
    for share in set(listdir(GROUP_PATH)) - set(local_classes) - set(local_options) - set(local_equipes) - set(local_etab_groups) - {'commun', 'professeurs', 'devoirs'}:
        subdestdir = path.join(RECYCLAGE_PATH, str(datetime.today().year))
        if not path.isdir(subdestdir):
            makedirs(subdestdir)
        destdir = path.join(subdestdir, share)
        if path.isdir(destdir):
            print("Une archive {} existe déjà, archivage du partage {} annulé".format(destdir, share))
            exit_code = 1
        else:
            print("Archivage du partage {}".format(share))
            move(path.join(GROUP_PATH, share), destdir)

#for local_group in local_groups:
#    print(str(local_group['cn']))
#    print(str(local_group['type']))
#    try:
#        print(str(local_group['sambasharemodel']))
#    except:
#        continue
#
#for local_share in local_shares:
#    #print(str(local_share['sambashareuri']))
#    #print(str(list(local_share['objectclass'])))
#    object_classes = [str(oc) for oc in local_share['objectclass']]
#    if 'classe' in object_classes:
#        partage = 'classe'
#    #meta_group._add_share(str(local_share['cn']), partage=partage)

meta_eleve.ldap_admin.connect()
meta_enseignant.ldap_admin = meta_eleve.ldap_admin
meta_administratif.ldap_admin = meta_eleve.ldap_admin
meta_share.ldap_admin = meta_eleve.ldap_admin
local_user_names = set()
for local_user in local_users:
    user_dn = local_user[0]
    login = str(local_user[1]['cn'][0])
    local_user_names.add(login)
    object_classes = [str(oc) for oc in local_user[1]['objectClass']]
    has_quota = get_quota(login) != 0
    args = {}
    if 'Eleves' in object_classes:
        typ = 'eleve'
        meta = meta_eleve
        user_class = str(local_user[1]['Divcod'][0])
        args['classe'] = user_class
        quota = QUOTA_STUDENT
        hard_quota = QUOTA_STUDENT_HARD
    elif 'administrateur' in object_classes:
        typ = 'professeur'
        meta = meta_enseignant
        quota = QUOTA_TEACHER
        hard_quota = QUOTA_TEACHER_HARD
    elif 'administratif' in object_classes:
        typ = 'administratif'
        meta = meta_administratif
        quota = QUOTA_ADMINISTRATIVE
        hard_quota = QUOTA_ADMINISTRATIVE_HARD
    else:
        continue
#    print('synchronisation de {} ({})'.format(login, typ))
    try:
        meta._add_perso(login, **args)
        meta._gen_groupesdir(login)
        meta._gen_ftpdir(login)
        if not has_quota:
            set_quota(login,
                      quota,
                      hard_quota,
                      )
    except Exception as err:
        print('impossible de synchroniser {} ({}) : {}'.format(login, typ, err))
        exit_code = 1

for login in set(listdir(AD_HOME_PATH)) - local_user_names - set(['mail']):
    # vérifie s'il n'y a pas eu une création à la main
    query = "(&(objectClass=user)(cn={}))".format(login)
    if not list(search(query)):
        subdestdir = path.join(RECYCLAGE_PATH, str(datetime.today().year))
        if not path.isdir(subdestdir):
            makedirs(subdestdir)
        destdir = path.join(subdestdir, login)
        if path.isdir(destdir):
            print("Une archive {} existe déjà, archivage de l'utilisateur {} annulé".format(destdir, login))
            exit_code = 1
        else:
            print("Archivage de l'utilisateur {}".format(login))
            move(path.join(AD_HOME_PATH, login), destdir)
if DEBUG:
    print(' * création des partages samba avec le filtre {}'.format(eoleshare.SHARE_FILTER))
meta_share._synchronize()
meta_eleve.ldap_admin.close()

if exit_code:
    print('')
    print('une erreur est survenue durant la synchronisation !')
    exit(exit_code)
