# -*- coding: iso-8859-1 -*-

####
# Copyright (C) 2006, 2007 Kim Gerdes
# kim AT gerdes.fr
#
# This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; either version 2
 # of the License, or (at your option) any later version.
#
# This script is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
# See the GNU General Public License (www.gnu.org) for more details.
#
# You can retrieve a copy of the GNU General Public License
# from http://www.gnu.org/.  For a copy via US Mail, write to the
#     Free Software Foundation, Inc.
#     59 Temple Place - Suite 330,
#     Boston, MA  02111-1307
#     USA
####

import string
import lefffDB
##from random import choice
import re

class FrenchLinguist:

    dic = lefffDB.Lefff()
    dataBaseStatus = dic.connect()
    motsPasApresQue = ["mais","enfin","bon"]
    listeClitiques=["je","j","me","m","tu","il","ils","elles","le","l",
                        "la","ne","n",
                        "te","t","en","y","lui","se","s","vous","nous","leur"]
    dicClitPersSource = {1:["je","j","nous"],2:["tu","vous"]}
##    dicClitPersCible = {1:"je",2:"vous"}
    listeElis = ["je","te","me","se","le","la","ne","que","ce","de"]
    
    remplacements12 = [("je vous","vous me"),("je ne vous","vous ne me"),
                        ("vous vous","je me"),("vous ne vous","je ne me"),
                        ("nous vous","vous me"),("nous ne vous","vous ne me"),
                        ("je me","vous vous"),("je ne me","vous ne vous"),
                        ("je","vous"),("me","vous"),("mon","votre"),("mes","vos"),
                        ("ma","votre"),("vous","je"),("votre","ma")]
    # attention : l'ordre de ces entrées est important - on remplace d'abord les premières
    #               entrées et les autres seulement quand les premières ne se sont pas
    #               appliquées !
    
    
    def changePersonne(self,liste):
        """ fonction qui remplace les verbes par la personne contraire
            (la personne de l'interlocuteur ou du locuteur respectivement)
            et les pronoms qui vont avec.
            - c'est un peu un bricolage pas très élégant - il n'y a rien
            d'universel ou de profondement linguistique dans cette fonction...
            (le plus difficile est de remplacer la suite de pronoms une fois
            et ne pas une deuxième fois, même si la liste de remplacment le
            permettait...)
        """
        #  on trouve les verbes à la 1ère personne qu'il faudra remplacer
        indexVerbes1 = self.candidatsVerbaux(self.dicClitPersSource[1],liste)
        # et on les remplace
        for i in indexVerbes1:
            liste[i] = self.dic.changePersonne(liste[i],1,2)

        #  on trouve les verbes à la 2e personne qu'il faudra remplacer
        indexVerbes2 = self.candidatsVerbaux(self.dicClitPersSource[2],liste)
        # et on les remplace (si ce n'est pas déjà le résultat d'un remplacement)
        for i in indexVerbes2:
            if i not in indexVerbes1:
                liste[i] = self.dic.changePersonne(liste[i],2,1,pluriel=False)

        # on passe aux pronoms :
        nouvelleListe=["" for mot in liste]

        for cle,valeur in self.remplacements12: # chaque remplacement
            listeMotsAvant = cle.split()
            listeMotsApres = valeur.split()
            neuf = self.remplaceSousListe(listeMotsAvant,listeMotsApres,liste)
            # copier tout ce qui est nouveau s'il n'y a pas déjà un remplacement
            for index, mot in enumerate(liste):
                if nouvelleListe[index] == "" and mot != neuf[index]:
                    nouvelleListe[index] = neuf[index]
        # remplacer les mots qui n'ont pas été touchés :
        for index,mot in enumerate(nouvelleListe):
            if mot == "" :
                nouvelleListe[index]=liste[index]

        return nouvelleListe
        
        

    def candidatsVerbaux(self,liste2cles,liste2mots):
        """ rend une liste d'indices de verbes qui suivent certaines clés,
            par exemple 'je' ou 'j'.
            par exemple, pour la input
            "hier, je ne lui en ai rien donné, et j'en suis fier"
            (nettoyée et splittée)
            il faut rendre [6,12]
        """

        # drapeau pour nous indiquer quand on est en train de passer au dessus
        # des clitiques :
        alerte = False
        liste = [] # contiendra les indices des verbes à regarder

        for index,mot in enumerate(liste2mots):
            if alerte and (mot not in self.listeClitiques) :
                # si je suis en train de passer sur les clitiques
                # et soudainement, ce n'est plus un clitique, alors
                # je suppose que j'ai trouvé le verbe à traiter
                liste.append(index)
                alerte = False
            if mot in liste2cles:
                alerte = True
        return liste

    def decontracte(self,chaine):
        for clitique in self.listeElis:
            # pour chaque clitique qui pourrait être élisé

            # crée une cdc avec la forme élisée suivi d'une lettre quelconque
            # par exemple " qu'(\w)"
            e = clitique[:-1]
            regsSourceString = " "+e+"'([éêèùûîô\w])"
            # en faire une expression régulière
            regSourceExp = re.compile(regsSourceString)
            # crée une cdc de remplacement
            # par exemple " que \1"
            regsCibleString = r"\1"
            regsCibleString = " "+clitique+" "+ regsCibleString
            # ici se fait le vrai travail : ,re.UNICODE
            chaine = (regSourceExp.sub(regsCibleString," "+chaine))[1:]

        return chaine
        
        


    def beautifier(self,chaine):
        """ fonction pour printer des lignes qui ont été travaillées
            et où il est donc possible qu'il manque certaines élisions
        """
	#print "___"+chaine
        # posttraitement :
        # pour l'instant seulement des élisions
        for clitique in self.listeElis:
            # pour chaque clitique à éliser
	    #print clitique
            # crée une cdc avec ce clitique plus une voyelle
            regsSourceString = "[ ']"+clitique+" ([aeiouyéêèùûîô])"
	    #uStr = unicode("田リチャー", "utf-8")
	    #regsSourceString = unicode(regsSourceString,"iso-8859-1")
	    #regsSourceString = regsSourceString.decode("iso-8859-1")
            # en faire une expression régulière
            regSourceExp = re.compile(regsSourceString)
            # crée une cdc de remplacement
            # (guillemet simple suivi de ce qu'on a trouvé en premier :
            #   donc la voyelle)
            regsCibleString = r"'\1"
            # ajouter le clitique sans son dernier caractère devant
            # cela part de l'idée qu'on n'a toujours qu'un caractère
            # à enléver
            regsCibleString = " "+clitique[:-1]+regsCibleString
	    #regsCibleString = unicode(regsCibleString,"iso-8859-1")
	    #regsCibleString = regsCibleString.decode("iso-8859-1")
	    #regsCibleString = unicode(regsCibleString)
            # ici se fait le vrai travail :
            # à l'aide de l'expression régulière source,
            # nous remplaçons cette expression par le cible dans
            # la chaîne à traiter content.decode(encoding)).encode(encoding)
	    #encoding = "iso-8859-1"
	    #chaine = unicode(" "+chaine,"utf-8")
	    #.decode(encoding).encode(encoding)
            chaine = (regSourceExp.sub(regsCibleString," "+chaine))[1:]

        chaine = re.sub(" +"," ",chaine)

        # on recode pour que ça s'affiche bien
##        chaine = self.recode(chaine)
        return chaine
        
        


    def recode(self,chaine):
        # nécessaire pour windows,
        # à enlever quand on est en ligne de commande de linux
        # cela sert à choisir le bon encodage si possible pour que
        # les lettres accentuées restent toujours lisibles
        try :
            chaine = unicode(chaine,"iso-8859-1").encode('cp437')
        except UnicodeEncodeError:
            chaine = unicode(chaine,"cp437").encode('iso-8859-1')
        return chaine

        
    def remplaceSousListe(self,sousListeAvant,sousListeApres,liste):
        """ fonction utilise un double underscore '__' et aucun mot des
            listes peut donc contenir ces deux caratères à la suite
            c'est ainsi qu'on peut avoir recours aux expressions régulières
            pour ne pas refaire le même travail pour les listes
        """

        # on crée des chaînes de caractères à partir des listes de manière
        # que entre les mots (ou expressions) se trouve des caractères uniques
        # et on a choisi "__" mais ça pourrait être n'importe quoi d'autre tant
        # que ça n'apparaît pas dans les mots à traiter
        li = "__".join(liste)
        av = "__".join(sousListeAvant)
        ap = "__".join(sousListeApres)

        # on utilise les regex pour remplacer
        res = re.sub("__"+av+"__","__"+ap+"__","__"+li+"__")
        # et on divise à nouveau dans une liste
        resultat = res.split("__")
        # on enlève les vides au début et à la fin
        # (provenant des caractères "__" au début et à la fin)
        resultat.pop()
        resultat.pop(0)
        # on rend le résultat.
        return resultat
        
        


    def choisirBonnePhrase(self,liste2phrases):
        """ prend par défaut une phrase où le patient
            parle de lui-même, sinon la dernière
        """
        bonnePhrase = ""
        for clit in ["je","nous","vous"]:
            # pour chaque clitique qu'on sait retourner
            for phrase in liste2phrases: # pour chaque phrase
                if len(phrase) > 1 :  bonnePhrase = phrase
                # si on a trouvé une phrase avec un bon clitique, on s'arrête
                if clit in phrase: break
        return bonnePhrase


    def nettoyerTexte(self,texte):
        """ nettoie le texte en le mettant en minuscules
            et en enlevant toute ponctuation
        """
        propre = texte.lower()
        for c in string.punctuation+"«»":
            propre=propre.replace(c," ")
        return propre
	
    def phraseEnchassee(self,input):
	    
	input.replace("M.","M") # pour éviter qu'on coupe après M. quand on divise l'input en phrases
	phrases = input.split(".")
	
	bonnePhrase = self.choisirBonnePhrase(phrases)
	phraseSplit = (self.nettoyerTexte(bonnePhrase)).split()

	# enlever des mots bizarre devant :
	while len(phraseSplit)>1 and phraseSplit[0] in self.motsPasApresQue: phraseSplit.pop(0)
	phraseRemaniee = " ".join(self.changePersonne(phraseSplit))
	if self.dic.contientVerbe(phraseSplit):
		return self.beautifier( " que "+phraseRemaniee+" ?")
	else :
		return self.beautifier( " '"+phraseRemaniee+"' ?")

        
        
#f = FrenchLinguist()  
#print f.imprime("qsdf le éee")
#print f.decontracte("j'adore j'évite j'y vais")
#print "qsdf"