
from pymongo import MongoClient
import Ela_Spacy as ls
import prj_common as mycommon
import inspect

client = MongoClient("mongodb://localhost:27017/")
# database
db = client["cherifdb"]
# collection

'''
Cette fonction indexe une formation
'''
def ela_index_class(external_code="", source_field = ""):
    try:

        collection = db["myclass"]

        if( len(str(source_field)) == 0):
            source_field = 'default'


        for doc in collection.find({"external_code":external_code}):
            if ( str(source_field) == "default" ):
                chaine = doc["title"]+" - "+doc["description"]
                #mycommon.myprint(" external_code = "+str(doc["external_code"])+" ==> "+str(chaine))
                retval = ls.ela_index_record_field(chaine, str(doc["external_code"]), source_field)

                '''
                # Apres indexation, on met a jour la formation pour 
                # mettre le champ "indexe" a 1.
                '''
                if( retval ):
                    # mise à jour du champ "indexed"
                    myobjectif = {}
                    myobjectif['indexed'] = '1'

                    ret_val2 = collection.find_and_modify(query={"external_code":external_code},
                                                        update={"$set": myobjectif}
                                                        )

                    if (ret_val2 and ret_val2['_id']):
                        mycommon.myprint("La formation indexée (champs par defaut) =" + str(ret_val2['_id']))
                        return True
                    else:
                        return False

            elif ( str(source_field) == "title" ):
                    chaine = doc["title"]
                    # mycommon.myprint(" external_code = "+str(doc["external_code"])+" ==> "+str(chaine))
                    retval = ls.ela_index_record_field(chaine, str(doc["external_code"]), source_field)

                    '''
                    # Apres indexation, on met a jour la formation pour 
                    # mettre le champ "indexe" a 1.
                    '''
                    if (retval):
                        # mise à jour du champ "indexed"
                        myobjectif = {}
                        myobjectif['indexed_title'] = '1'

                        ret_val2 = collection.find_and_modify(query={"external_code": external_code},
                                                              update={"$set": myobjectif}
                                                              )

                        if (ret_val2 and ret_val2['_id']):
                            mycommon.myprint("La formation indexée (champ title) =" + str(ret_val2['_id']))
                            return True
                        else:
                            return False

            elif ( str(source_field) == "description" ):
                    chaine = doc["description"]
                    # mycommon.myprint(" external_code = "+str(doc["external_code"])+" ==> "+str(chaine))
                    retval = ls.ela_index_record_field(chaine, str(doc["external_code"]), source_field)

                    '''
                    # Apres indexation, on met a jour la formation pour 
                    # mettre le champ "indexe" a 1.
                    '''
                    if (retval):
                        # mise à jour du champ "indexed"
                        myobjectif = {}
                        myobjectif['indexed_desc'] = '1'

                        ret_val2 = collection.find_and_modify(query={"external_code": external_code},
                                                              update={"$set": myobjectif}
                                                              )

                        if (ret_val2 and ret_val2['_id']):
                            mycommon.myprint("La formation indexée (champ description) =" + str(ret_val2['_id']))
                            return True
                        else:
                            return False

            elif ( str(source_field) == "objectif" ):
                    chaine = doc["objectif"]
                    # mycommon.myprint(" external_code = "+str(doc["external_code"])+" ==> "+str(chaine))
                    retval = ls.ela_index_record_field(chaine, str(doc["external_code"]), source_field)

                    '''
                    # Apres indexation, on met a jour la formation pour 
                    # mettre le champ "indexe" a 1.
                    '''
                    if (retval):
                        # mise à jour du champ "indexed"
                        myobjectif = {}
                        myobjectif['indexed_obj'] = '1'

                        ret_val2 = collection.find_and_modify(query={"external_code": external_code},
                                                              update={"$set": myobjectif}
                                                              )

                        if (ret_val2 and ret_val2['_id']):
                            mycommon.myprint("La formation indexée (champs objectif) =" + str(ret_val2['_id']))
                            return True
                        else:
                            return False


        return True
    except Exception as e:
        mycommon.myprint(e)
        return False


'''
La fonction "ela_index_all_classes" va aller chercher chaque cours dans la BDD
et créer les mots clées qui sont ensuite enregister dans la table "elaindex" 
'''

def ela_index_all_classes():
# Making a Connection with MongoClient
    try:
        # collection
        collection = db["myclass"]
        '''
        ATTENTION ATTENTION 
        /!\ : avant l'indexation, on vide la table des indexes.
        cette logique est tres gourmande.
        ce quil faudrait faire :
        - si une formation est indexée, mettre un fag pour dire : indexé => OK
        - si on met à jour une formation ==> Mettre le flag à KO
        - si on ajoute une formation, mettre le flag à KO
        
        Pour mutualiser le process entre l'indexation des tous les champs ou l'indexation de uniquement de certain champs
        ex : indexation du champ 'title' ou du champ 'objectif', je vais introduitre la notion de 'source_fied'
        pour l'indexation title, 'source_fied' = 'title'
        pour l'indexation objectif, 'source_fied' = 'objectif'
        
        apres pour l'indexation, il ne faudra indexer que les formation dont le flag est KO.
        aussi, avant d'indexer une formation, supprimer tous les index de la dite formation pour remplacer tous les anciens et eviter un doublon
        '''

        nb_class_indexed = 0
        for doc in collection.find({'indexed':'0'}):
            chaine = doc["title"]+" - "+doc["description"]
            mycommon.myprint(" external_code = "+str(doc["external_code"])+" ==> "+str(chaine))
            retval = ela_index_class(str(doc["external_code"]))
            print(" apres : ela_index_class retval =  "+str(retval))

            if( retval is False):
                mycommon.myprint("IMPOSSIBLE d'indexer la formation = " + str(doc["external_code"]))
            else:
                nb_class_indexed = nb_class_indexed+1


            #retval = ls.ela_index_record_field(chaine, str(doc["external_code"]))

        mycommon.myprint(str(nb_class_indexed)+" ont été indexes")
        return True, str(nb_class_indexed)+" ont été indexes "

    except Exception as e:
        mycommon.myprint(e)
        return False, "Impossible d'indexer la BDD des formations ==> KO"


'''
La fonction "ela_index_all_classes_title" va aller chercher chaque cours dans la BDD
et créer les mots clées  des title qui sont ensuite enregister dans la table "elaindex" 
'''


def ela_index_all_classes_title():
    # Making a Connection with MongoClient
    try:
        client = MongoClient("mongodb://localhost:27017/")
        # database
        db = client["cherifdb"]
        # collection
        collection = db["myclass"]
        '''
        ATTENTION ATTENTION 
        /!\ : avant l'indexation, on vide la table des indexes.
        cette logique est tres gourmande.
        ce quil faudrait faire :
        - si une formation est indexée, mettre un fag pour dire : indexé => OK
        - si on met à jour une formation ==> Mettre le flag à KO
        - si on ajoute une formation, mettre le flag à KO

        
        ex : indexation du champ 'title' ou du champ 'objectif', je vais introduitre la notion de 'source_fied'
        pour l'indexation title, 'source_fied' = 'title'
        pour l'indexation objectif, 'source_fied' = 'objectif'

        apres pour l'indexation, il ne faudra indexer que les formation dont le flag est KO.
        aussi, avant d'indexer une formation, supprimer tous les index de la dite formation pour remplacer tous les anciens et eviter un doublon
        '''

        nb_class_indexed = 0
        for doc in collection.find({'indexed_title': '0'}):
            chaine = doc["title"]
            mycommon.myprint(" external_code = " + str(doc["external_code"]) + " ==> " + str(chaine))
            retval = ela_index_class(str(doc["external_code"]), "title")
            print(" apres : ela_index_all_classes_title retval =  " + str(retval))

            if (retval is False):
                mycommon.myprint("IMPOSSIBLE d'indexer la formation = " + str(doc["external_code"]))
            else:
                nb_class_indexed = nb_class_indexed + 1

            # retval = ls.ela_index_record_field(chaine, str(doc["external_code"]))

        mycommon.myprint(str(nb_class_indexed) + " ont été indexes")
        return True, str(nb_class_indexed) + " ont été indexes "

    except Exception as e:
        mycommon.myprint(e)
        return False, "Impossible d'indexer la BDD des formations ==> KO"


'''
La fonction "ela_index_all_classes_desc" va aller chercher chaque cours dans la BDD
et créer les mots clées  des "description" qui sont ensuite enregister dans la table "elaindex" 
'''

def ela_index_all_classes_desc():
    # Making a Connection with MongoClient
    try:
        client = MongoClient("mongodb://localhost:27017/")
        # database
        db = client["cherifdb"]
        # collection
        collection = db["myclass"]
        '''
        ATTENTION ATTENTION 
        /!\ : avant l'indexation, on vide la table des indexes.
        cette logique est tres gourmande.
        ce quil faudrait faire :
        - si une formation est indexée, mettre un fag pour dire : indexé => OK
        - si on met à jour une formation ==> Mettre le flag à KO
        - si on ajoute une formation, mettre le flag à KO


        ex : indexation du champ 'title' ou du champ 'objectif', je vais introduitre la notion de 'source_fied'
        pour l'indexation title, 'source_fied' = 'title'
        pour l'indexation objectif, 'source_fied' = 'objectif'

        apres pour l'indexation, il ne faudra indexer que les formation dont le flag est KO.
        aussi, avant d'indexer une formation, supprimer tous les index de la dite formation pour remplacer tous les anciens et eviter un doublon
        '''

        nb_class_indexed = 0
        for doc in collection.find({'indexed_desc': '0'}):
            chaine = doc["description"]
            mycommon.myprint(" external_code = " + str(doc["external_code"]) + " ==> " + str(chaine))
            retval = ela_index_class(str(doc["external_code"]), "description")
            print(" apres : ela_index_all_classes_title retval =  " + str(retval))

            if (retval is False):
                mycommon.myprint("IMPOSSIBLE d'indexer la formation = " + str(doc["external_code"]))
            else:
                nb_class_indexed = nb_class_indexed + 1

            # retval = ls.ela_index_record_field(chaine, str(doc["external_code"]))

        mycommon.myprint(str(nb_class_indexed) + " ont été indexes - champ description")
        return True, str(nb_class_indexed) + " ont été indexes - champ description "

    except Exception as e:
        mycommon.myprint(e)
        return False, "Impossible d'indexer la BDD des formations ==> KO"


'''
La fonction "ela_index_all_classes_desc" va aller chercher chaque cours dans la BDD
et créer les mots clées  des "objectif" qui sont ensuite enregister dans la table "elaindex" 
'''

def ela_index_all_classes_obj():
    # Making a Connection with MongoClient
    try:
        # collection
        collection = db["myclass"]
        '''
        ATTENTION ATTENTION 
        /!\ : avant l'indexation, on vide la table des indexes.
        cette logique est tres gourmande.
        ce quil faudrait faire :
        - si une formation est indexée, mettre un fag pour dire : indexé => OK
        - si on met à jour une formation ==> Mettre le flag à KO
        - si on ajoute une formation, mettre le flag à KO


        ex : indexation du champ 'title' ou du champ 'objectif', je vais introduitre la notion de 'source_fied'
        pour l'indexation title, 'source_fied' = 'title'
        pour l'indexation objectif, 'source_fied' = 'objectif'

        apres pour l'indexation, il ne faudra indexer que les formation dont le flag est KO.
        aussi, avant d'indexer une formation, supprimer tous les index de la dite formation pour remplacer tous les anciens et eviter un doublon
        '''

        nb_class_indexed = 0
        for doc in collection.find({'indexed_obj': '0'}):
            chaine = doc["objectif"]
            mycommon.myprint(" external_code = " + str(doc["external_code"]) + " ==> " + str(chaine))
            retval = ela_index_class(str(doc["external_code"]), "objectif")
            print(" apres : ela_index_all_classes_title retval =  " + str(retval))

            if (retval is False):
                mycommon.myprint("IMPOSSIBLE d'indexer la formation = " + str(doc["external_code"]))
            else:
                nb_class_indexed = nb_class_indexed + 1

            # retval = ls.ela_index_record_field(chaine, str(doc["external_code"]))

        mycommon.myprint(str(nb_class_indexed) + " ont été indexes - champ objectif")
        return True, str(nb_class_indexed) + " ont été indexes - champ objectif "

    except Exception as e:
        mycommon.myprint(e)
        return False, "Impossible d'indexer la BDD des formations ==> KO"





'''
Cette fonction recherche une chaine de caractère
dans la base de données.

cette recherche concerne les 'tuple' avec "source_field":"default" ==> l'indexation par defaut.

Elle retourne l'id_externe de la formation
'''
def ela_recherche_tokens(sentence):
    tab_training_id = []
    tab_tokens = ls.Ela_Tokenize(sentence)
    tab_tokens2 = ls.Ela_remove_stop_words(tab_tokens)
    tab_tokens3 = ls.Ela_remove_pronoun(tab_tokens2)
    tab_tokens4 = ls.Ela_stemmize(tab_tokens3)
    tab_tokens4.sort()

    '''
    tab_tokens4 contient la liste des mots à rechercher.
    En suite pour chaque mot de "tab_tokens4" on regarde dans la table  "elaindex"
    a quoi cela pourrait correspondre.
    '''

    # collection
    collection = db["elaindex"]


    for token in tab_tokens4:
        print(token)
        for doc in collection.find({"mots":token, "source_field":"default"}):
            #print(" Trouvé dans le cours N° "+str(doc["id_formation"]))
            if str(doc["id_formation"]) not in tab_training_id :
                tab_training_id.append(str(doc["id_formation"]))

    print(" Pour la phrase "+str(sentence)+", voici les formations correspondantes")
    print(tab_training_id)

    return tab_training_id




'''
Cette fonction recherche une chaine de caractère
dans la base, mais sur indexation bien precise.

par exemple, pour gerer les recherche par tips :'title':'sentense', le système cherchera a identifier
les mots de "sentense" dans les indexation des titre. 
Cela revient a chercher "sentence" dans la table "ela_index", where "source_field" = "title"

Elle retourne l'id_externe de la formation
'''
def ela_recherche_tokens_source_field(sentence, source_fied=""):

    if( len(str(source_fied)) == 0):
        mycommon.myprint(str(inspect.stack()[0][3])+" - source_fied est vide")
        return False

    # Verification que source_field correspond a la bonne colonne
    field_list = ['default', 'title', 'description','objectif']
    if source_fied not in field_list:
        mycommon.myprint(str(inspect.stack()[0][3])+" -  Le champ  '" + source_fied + "' n'existe pas, requete annulée")
        return False

    tab_training_id = []
    tab_tokens = ls.Ela_Tokenize(sentence)
    tab_tokens2 = ls.Ela_remove_stop_words(tab_tokens)
    tab_tokens3 = ls.Ela_remove_pronoun(tab_tokens2)
    tab_tokens4 = ls.Ela_stemmize(tab_tokens3)
    tab_tokens4.sort()

    '''
    tab_tokens4 contient la liste des mots à rechercher.
    En suite pour chaque mot de "tab_tokens4" on regarde dans la table  "elaindex"
    a quoi cela pourrait correspondre.
    '''

    collection = db["elaindex"]


    for token in tab_tokens4:
        print(token)
        for doc in collection.find({"mots":token, "source_field":source_fied}):
            #print(" Trouvé dans le cours N° "+str(doc["id_formation"]))
            if str(doc["id_formation"]) not in tab_training_id :
                tab_training_id.append(str(doc["id_formation"]))

    print(" Pour la phrase "+str(sentence)+", voici les formations correspondantes")
    print(tab_training_id)

    return tab_training_id

