# -*- coding: utf-8 -*-
###########################################################################
# Eole NG - 2009
# Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
# Licence CeCill  cf /root/LicenceEole.txt
# eole@ac-dijon.fr
###########################################################################
"""
    définition des formats de données internes pour l'importation
"""
#from axiom.item import Item
#from axiom.store import Store
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.types import Boolean, Text, Integer
from sqlalchemy import Column, Table, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine, orm
from os.path import isfile
from os import makedirs, unlink


Item = declarative_base()


def init_store(dbdir=None, delete=True):
    """
    Initialisation de la base
    """
    dbfile = f'{dbdir}.db'
    if isfile(dbfile) and delete:
        unlink(dbfile)
    engine = create_engine('sqlite:///%s' % dbfile)
    session = orm.sessionmaker(autocommit=True, bind=engine)()
    true_add = session.add
    def findOrCreate(model, **kwargs):
        instance = session.query(model).filter_by(**kwargs).first()
        if instance:
            return instance
        instance = model(**kwargs)
        session.add(instance)
        return instance

    def add(*args, **kwargs):
        true_add(*args, **kwargs)
        session.flush()
    session.findOrCreate = findOrCreate
    session.add = add
    Item.metadata.create_all(engine)
    return session


class Eleve(Item):
    """
    Eleve
    """
    __tablename__ = 'eleve'
    # arguments obligatoires
    id = Column("id", Integer, primary_key=True) # id interne
    int_id = Column("int_id", Integer, index=True)
    nom = Column("name", Text)
    prenom = Column("prenom", Text)
    date = Column("date", Text)
    numero = Column("numero", Text)
    civilite = Column("civilite", Text) # attendu 1/2/3
    # arguments facultatifs
    classe_id = Column(Integer, ForeignKey('classe.id'))
    classe = relationship('Classe', back_populates='eleves')
    niveau_id = Column(Integer, ForeignKey('niveau.id'))
    niveau = relationship('Niveau', back_populates='eleves')
    prenom2 = Column("prenom2", Text, default='')
    nom_patronymique = Column("nom_patronymique", Text, default='')
    ine = Column("ine", Text, default='')
    entpersonjointure = Column("entpersonjointure", Text, default='')
    rattachid = Column("rattachid", Text, default='')
    regime = Column("regime", Text, default='')
    enseignements = Column("enseignements", Text, default='[]')
    # login ldap attribué après traitement
    login = Column("login", Text, default='')
    # login forcé (import CSV)
    force_login = Column("force_login", Text)
    force_password = Column("force_password", Text)
    groupes = relationship("JointureGroupeEleve", back_populates='eleve')
    responsables = relationship("JointureResponsableEleve", back_populates='eleve')

    def get_groupes(self):
        """
            :return: les groupes correspondant à cet élève
        """
        return [groupe.groupe for groupe in self.groupes]


class Responsable(Item):
    """
    Responsable
    """
    __tablename__ = 'responsable'
    # arguments obligatoires
    id = Column("id", Integer, primary_key=True) # id interne
    int_id = Column("int_id", Integer, index=True)
    nom = Column("nom", Text)
    prenom = Column("prenom", Text)
    # arguments facultatifs
    civilite = Column("civilite", Text, default='')
    date = Column("date", Text, default='')
    mail = Column("mail", Text, default='')
    telephone = Column("telephone", Text, default='')
    tel_portable = Column("tel_portable", Text, default='')
    tel_pro = Column("tel_pro", Text, default='')
    entpersonjointure = Column("entpersonjointure", Text, default='')
    # -> class Adress
    id_adresse = Column("id_adresse", Text, index=True)
    adresse_id = Column(Integer, ForeignKey('adresse.id'))
    adresse = relationship('Adresse', back_populates='responses')
    # login ldap attribué après traitement
    login = Column("login", Text, default='') # initialisé au traitement
    eleves = relationship("JointureResponsableEleve", back_populates='responsable')

    def get_eleves(self):
        """
            :return: les élèves correspondant à ce responsable
        """
        return [eleve.eleve for eleve in self.eleves]


class Adresse(Item):
    """
    Adresse
    """
    __tablename__ = 'adresse'
    id = Column("id", Integer, primary_key=True) # id interne
    int_id = Column("int_id", Integer, index=True)
    adresse = Column("adresse", Text, default='')
    code_postal = Column("code_postal", Text, default='')
    ville = Column("ville", Text, default='')
    pays = Column("pays", Text, default='')
    responses = relationship('Responsable', back_populates="adresse")


class JointureResponsableEleve(Item):
    """
    Jointure Responsable - Eleve
    """
    __tablename__ = 'jointure_responsable_eleve'
    id = Column("id", Integer, primary_key=True) # id interne
    eleve_id = Column(Integer, ForeignKey('eleve.id'))
    eleve = relationship('Eleve')
    responsable_id = Column(Integer, ForeignKey('responsable.id'))
    responsable = relationship('Responsable')
    # utilité de ce qui suit ?
    resp_legal = Column("resp_legal", Text, default='')
    resp_financier = Column("resp_financier", Text, default='')
    resp_paiement = Column("resp_paiement", Text, default='')
    pers_contact = Column("pers_contact", Text, default='')
    code_parente = Column("code_parente", Text, default='')


class Classe(Item):
    """
        classe
    """
    __tablename__ = 'classe'
    id = Column("id", Integer, primary_key=True)
    nom = Column("nom", Text, index=True) # modifiable au traitement
    niveau_id = Column(Integer, ForeignKey('niveau.id'))
    niveau = relationship('Niveau', back_populates='classes')
    eleves = relationship('Eleve', back_populates='classe')

    def get_eleves(self):
        """
            :return: les élèves correspondant à cette classe
        """
        return self.eleves


class Niveau(Item):
    """
        niveau
    """
    __tablename__ = 'niveau'
    id = Column("id", Integer, primary_key=True)
    nom = Column("nom", Text, index=True) # modifiable au traitement
    classes = relationship('Classe', back_populates='niveau')
    eleves = relationship('Eleve', back_populates='niveau')

    def get_eleves(self):
        """
            :return: les élèves correspondant à cette classe
        """
        return self.eleves


class Enseignant(Item):
    """
    Enseignant
    """
    __tablename__ = 'enseignant'
    # arguments obligatoires
    id = Column("id", Integer, primary_key=True) # id interne
    int_id = Column("int_id", Integer, index=True)
    nom = Column("nom", Text)
    prenom = Column("prenom", Text)
    date = Column("date", Text)
    # arguments facultatifs
    civilite = Column("civilite", Text, default='')
    mail = Column("mail", Text, default='')
    nom_patronymique = Column("nom_patronymique", Text, default='')
    disciplines = Column("disciplines", Text, default='[]')
    entpersonjointure = Column("entpersonjointure", Text, default='')
    # login ldap attribué après traitement
    login = Column("login", Text, default='') # initialisé au traitement
    # login forcé (import CSV)
    force_login = Column("force_login", Text)
    force_password = Column("force_password", Text)
    classes = relationship("JointureClasseEnseignant", back_populates='enseignant')
    matieres = relationship("JointureMatiereEnseignant", back_populates='enseignant')
    groupes = relationship("JointureGroupeEnseignant", back_populates='enseignant')

    def get_classes(self):
        """
            :return: les classes correspondant à cet enseignant
        """
        return self.classes

    def get_matieres(self):
        """
            :return: les matières correspondant à cet enseignant
        """
        return [matiere.matiere for matiere in self.matieres]

    def get_groupes(self):
        """
            :return: les groupes correspondant à cet élève
        """
        return [groupe.groupe for groupe in self.groupes]


class Administratif(Item):
    """
    Personnel administratif
    """
    __tablename__ = 'administratif'
    # arguments obligatoires
    id = Column("id", Integer, primary_key=True) # id interne
    int_id = Column("int_id", Integer, index=True)
    nom = Column("nom", Text)
    prenom = Column("prenom", Text)
    date = Column("date", Text)
    # arguments facultatifs
    civilite = Column("civilite", Text, default='')
    mail = Column("mail", Text, default='')
    nom_patronymique = Column("nom_patronymique", Text, default='')
    groupe_ip = Column(Integer, ForeignKey('service.id'))
    groupe = relationship('Service', back_populates='administratifs')
    entpersonjointure = Column("entpersonjointure", Text, default='')
    # login ldap attribué après traitement
    login = Column("login", Text, default='') # initialisé au traitement
    # login forcé (import CSV v2)
    force_login = Column("force_login", Text)
    force_password = Column("force_password", Text)


class Invite(Item):
    """
    Compte invité
    """
    __tablename__ = 'invite'
    # arguments obligatoires
    id = Column("id", Integer, primary_key=True) # id interne
    nom = Column("nom", Text)
    prenom = Column("prenom", Text)
    date = Column("date", Text)
    # arguments facultatifs
    civilite = Column("civilite", Text, default='')
    mail = Column("mail", Text, default='')
    # login ldap attribué après traitement
    login = Column("login", Text, default='') # initialisé au traitement
    # login forcé (import CSV v2)
    force_login = Column("force_login", Text)
    force_password = Column("force_password", Text)


class JointureClasseEnseignant(Item):
    """
    Jointure Classe - Enseignant
    """
    __tablename__ = 'jointure_classe_enseignant'
    id = Column("id", Integer, primary_key=True) # id interne
    classe_id = Column(Integer, ForeignKey('classe2.id'))
    classe = relationship('EnsClasse')
    enseignant_id = Column(Integer, ForeignKey('enseignant.id'))
    enseignant = relationship('Enseignant')
    profprincipal = Column("profprincipal", Boolean, default=False)


class JointureMatiereEnseignant(Item):
    """
    Jointure Matiere - Enseignant
    """
    __tablename__ = 'jointure_matiere_enseignant'
    id = Column("id", Integer, primary_key=True) # id interne
    matiere_id = Column(Integer, ForeignKey('matiere.id'))
    matiere = relationship('Matiere')
    enseignant_id = Column(Integer, ForeignKey('enseignant.id'))
    enseignant = relationship('Enseignant')


class JointureGroupeEnseignant(Item):
    """
    Jointure Groupe - Enseignant
    """
    __tablename__ = 'jointure_groupe_enseignant'
    id = Column("id", Integer, primary_key=True) # id interne
    groupe_id = Column(Integer, ForeignKey('groupe.id'))
    groupe = relationship('Groupe')
    enseignant_id = Column(Integer, ForeignKey('enseignant.id'))
    enseignant = relationship('Enseignant')


class JointureGroupeEleve(Item):
    """
    Jointure Groupe - Eleve
    """
    __tablename__ = 'jointure_groupe_eleve'
    id = Column("id", Integer, primary_key=True) # id interne
    groupe_id = Column(Integer, ForeignKey('groupe.id'))
    groupe = relationship('Groupe')
    eleve_id = Column(Integer, ForeignKey('eleve.id'))
    eleve = relationship('Eleve')


class EnsClasse(Item):
    """
    Classe (fournie par un enseignant)
    """
    __tablename__ = 'classe2'
    id = Column("id", Integer, primary_key=True) # id interne
    nom = Column("nom", Text, index=True) # modifiable au traitement
    enseignants = relationship("JointureClasseEnseignant", back_populates='classe')


class Matiere(Item):
    """
    Matiere
    """
    __tablename__ = 'matiere'
    id = Column("id", Integer, primary_key=True) # id interne
    nom = Column("nom", Text, index=True) # modifiable au traitement
    description = Column("description", Text, default='')
    enseignants = relationship("JointureMatiereEnseignant", back_populates='matiere')


class Groupe(Item):
    """
    Groupe
    """
    __tablename__ = 'groupe'
    id = Column("id", Integer, primary_key=True) # id interne
    nom = Column("nom", Text, index=True) # modifiable au traitement
    description = Column("description", Text, default='')
    eleves = relationship("JointureGroupeEleve", back_populates='groupe')
    enseignants = relationship("JointureGroupeEnseignant", back_populates='groupe')

    def count_members(self):
        """
            :return: nombre d'utilisateurs inscrits au groupe
        """
        return len(self.eleves) + len(self.enseignants)


class Service(Item):
    """
    Service administratif
    """
    __tablename__ = 'service'
    id = Column("id", Integer, primary_key=True) # id interne
    nom = Column("nom", Text, index=True) # modifiable au traitement
    description = Column("description", Text, default='')
    administratifs = relationship("Administratif", back_populates='groupe')


#association_table = Table('jointure_groupe_user', Item.metadata,
#    Column('groupe', Integer, ForeignKey('groupe.id')),
#    Column('user', Integer, ForeignKey('user.id'))
#)
