from __future__ import unicode_literals
# -*- coding: utf-8 -*-

import os, sys, time, threading, socket, logging, subprocess
import cPickle as pickle

#import de QT et des interfaces
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from ecran_connexion import Ui_ecranConnexion
from ecran_chat import Ui_chat

#modules persos
from serveur import Serveur, ServeurVoc
from lancer import jet
#from clientvoc import ClientVoc

#parametres deboguage
logging.basicConfig(level=logging.DEBUG,
                    format='(%(threadName)-10s) %(message)s',
                    )

class EcranConnexion(QGroupBox):
    """fenetre de connexion a l'application et module d'envoi/reception"""
    def __init__(self, parent=None):
        """initialisation de la connexion et creation de la fenetre"""
        super (EcranConnexion, self).__init__(parent)
        self.client_connecte = False
        self.serveur_connecte = False
        self.idClient = "00"
        self.ip = ""
        self.pseudo = ""
        self.autresCo = {}
        
        #echanges fichiers
        #self.idFichier = "00"
        self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule" : False}
                           #fichier en cours d'envoi : id fichier, chemin du fichier, fichier (objet), dest, envoi autorise, envoi annule
        self.destFichier = {}   #liste des clients dont on attend confirmation pour l'envoi de fichier
        self.receptionFichier = {} #id du fichier: nom du fichier
        self.repReceptionFichiers = "C:\\"
        
        #chat voc
        self.ipServeurVoc = ""
        self.port = 6660

        #recup des param et affichage:
        try:
            print(self.recupParamCo())
        except:
            print("pas de parametres a recuperer")
        self.createWidgets()

    def createWidgets(self):
        """creation de l'interface de connexion"""
        self.ui = Ui_ecranConnexion()
        self.ui.setupUi(self)
        if len(self.ip) > 0:
            self.ui.in_ip.setText(QString.fromUtf8(self.ip))
        if self.port > 0:
            self.ui.in_port.setText(QString.fromUtf8(str(self.port)))
        if len(self.pseudo) > 0:
            self.ui.in_pseudo.setText(QString.fromUtf8(self.pseudo))
            
        self.connect(self.ui.fermer, SIGNAL("clicked()"), self.fermer)
        self.connect(self.ui.creerServeur, SIGNAL("clicked()"), self.creerServeur)
        self.connect(self.ui.seConnecter, SIGNAL("clicked()"), self.seConnecter)

    def msg(self, txt):
        """affichage d'un message informatif sous forme de label"""
        self.ui.txt_msg.setText(QString.fromUtf8(txt))
        QApplication.processEvents()

    def creerServeur(self):
        """instancie un serveur local"""
        self.pseudo = self.ui.in_pseudo.text()
        self.port = self.ui.in_port.text()        
        if len(self.pseudo) == 0 or len(self.port) == 0:
            self.msg("Parametres incorrects")
        else:    
            self.ui.in_ip.setText(QString.fromUtf8("localhost"))
            self.s = Serveur(int(self.ui.in_port.text()))
            self.serveur_connecte, txt = self.s.creer()
            self.msg(txt)
            if self.serveur_connecte:
               self.seConnecter()

    def seConnecter(self):
        """se connecte au serveur correspondant a l'ip et au port saisis"""
        self.pseudo = self.ui.in_pseudo.text()
        self.port = self.ui.in_port.text()
        self.ip = self.ui.in_ip.text()
        essais = 0
        if len(self.pseudo) == 0 or len(self.ip) == 0 or len(self.port) == 0:
            self.msg("Parametres incorrects")
        else:    
            self.msg("En attente du serveur...")    
            while self.client_connecte == False:
            #en attente de la connexion    
                try:
                   self.cnn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                   self.cnn.connect((self.ip, int(self.port)))
                   self.client_connecte = True
                   txt = "Connexion etablie avec le serveur sur le port {}\n".format(self.port)
                except KeyboardInterrupt:
                   break
                except:
                   essais += 1
                   if essais > 3:
                       self.msg("Delai depasse")
                       break
                   self.msg("Connexion : essai {}".format(essais))  

        if self.client_connecte:
            #demarre le fil de reception
            threading.Thread(None, self.filReception, None, (), {}).start()
            #previent le serveur et envoie le pseudo
            self.envoi("ci", "sa", self.pseudo)
            self.msg(txt)
            time.sleep(0.01)
            self.close()
            self.emit(SIGNAL("majAffichage()"))
        else:
            self.msg("Erreur: impossible de se connecter")
            
    
    def filReception(self):
        """thread de reception des donnees du serveur, reste actif tant que l'application est active"""
        while self.client_connecte:
           recu = self.cnn.recv(1024)
           if len(recu) > 0:
               self.traitement(recu)
        
    def traitement(self, msg):
        """determine le traitement a apporter a un message recu, selon sa nature"""
        if len(msg) >= 6:        
            emet = msg[2:4]
            dest = msg[4:6]
            categorie = msg[:1]
            nature = msg[:2]
            try:
               contenu = msg[6:]
            except:
               contenu = "" 

            if nature != "fd" and nature != "ff":
                #on decode le message, sauf s'il contient des donnees binaires issues d'un fichier
                contenu = contenu.decode('utf-8')
            
            if nature == "ci":
                #recoit l'identifiant du client fourni par le serveur
                self.idClient = dest
                print("mon id est: {}\n".format(self.idClient))
                
            elif nature == "cc":
                if contenu[0:2] != self.idClient:
                    self.autresCo[str(contenu[0:2])] = str(contenu[2:])
                    #on lui envoie id+pseudo
                    time.sleep(0.02)
                    self.envoi("cp", contenu[0:2], "{}{}".format(self.idClient, self.pseudo))
                    print("{} s'est connecte ({})".format(contenu[2:], contenu[0:2]))
                    self.recuInfo("cc", "{} s'est connecte ({})".format(contenu[2:], contenu[0:2]))

            elif nature == "cp":
                self.autresCo[str(contenu[0:2])] = str(contenu[2:])
                time.sleep(0.01)
                print("{} est present ({})".format(contenu[2:], contenu[0:2]))
                self.recuInfo("cc", "{} est present ({})".format(contenu[2:], contenu[0:2]))

            elif nature == "cd":
                if contenu != self.idClient and len(contenu) == 2:
                    print("{} s'est deconnecte ({})".format(self.autresCo[contenu], contenu))
                    self.recuInfo("cd", "{} s'est deconnecte ({})".format(self.autresCo[contenu], contenu))
                    del self.autresCo[contenu]
                    
            elif categorie == "m":
                #afficher dans le chat
                print("chat: {} -> {}\n".format(emet, contenu))
                self.recuMsg(emet, contenu)
                
            elif categorie == "i":
                #afficher dans la fenetre évènement
                self.recuInfo(nature, contenu)
                if nature == "id":
                    #jet de dés: afficher en rouge
                    print("jet de dé: {} -> {}\n".format(emet, contenu))
                if nature == "ic":
                    #nouveau client connecte: afficher en bleu
                    print("info connexion: {} -> {}\n".format(emet, contenu))
                    
            elif categorie == "f":
                #envoi ou reception de fichier
                if nature == "f0":
                    #le serveur nous renvoie l'identifiant du fichier que l'on veut envoyer
                    if self.eFichier["id"] == "00":
                       if len(contenu) == 2:
                          threading.Thread(None, self.envoiFichier_1, None, (contenu,), {}).start()
                       else:
                          print("erreur: id du fichier\n")
                    else:
                       print("Un fichier est en cours d'envoi\n")
                       
                elif nature == "fp":
                    #un clients est pret a recevoir le fichier
                    self.pretEnvoiFichier(emet)

                elif nature == "fi":
                    #quelqu'un nous envoie un fichier
                    if len(contenu)>2:
                       #les 2 premiers car sont l'identifiant, puis le nom du fichier (* la taille)
                       essai = self.nouveauFichier(contenu[0:2], contenu[2:])
                       print("nouveau fichier: {}".format(essai))
                       if len(essai) > 0:
                           self.recuInfo(nature, "Fichier {} en cours de reception".format(contenu[2:]))
                           #on envoie confirmation de la reception:
                           time.sleep(0.001)
                           self.envoi("fp", emet, contenu[0:2])
                           self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(essai), QString.fromUtf8(""))
                       else:
                           self.recuInfo(nature, "Impossible de créer le fichier à recevoir")
                    else:
                       print("erreur reception fichier: id ou nom du fichier incorrect\n") 
                    
                elif nature == "fd":
                    #on recoit les donnees a ecrire dans le fichier
                    #print("reception: {}".format(contenu))
                    if len(contenu) > 2:
                        self.receptionFichier[contenu[0:2]].write(contenu[2:])
                        #print("{} -> paquet recu".format(contenu[0:2]))
                        self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("."))
                        
                        #le client renvoie la longueur de la donnee recue a l'emetteur pour confirmation
                        time.sleep(0.001)
                        self.envoi("fp", emet, contenu[0:2])
                    elif len(contenu) == 2:
                        #l'emetteur redemande confirmation, on lui envoie
                        self.envoi("fp", emet, contenu[0:2])
                    else:
                        print("erreur de reception des donnees du fichier\n")
                        #pass
                    
                elif nature == "ff":
                    #fin de reception du fichier
                    self.receptionFichier[contenu[0:2]].write(contenu[2:])
                    time.sleep(0.001)
                    self.envoi("fp", emet, contenu[0:2])
                    self.recuInfo("ff", "Fichier {} recu\n".format(os.path.basename(self.receptionFichier[contenu[0:2]].name)))
                    self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("ok"))
                    self.emit(SIGNAL("inserImg(QString, QString)"), QString.fromUtf8(emet), QString.fromUtf8(self.receptionFichier[contenu[0:2]].name))
                    time.sleep(0.01)
                    self.receptionFichier[contenu[0:2]].close()
                    del self.receptionFichier[contenu[0:2]]
                    print("fichier recu")
                    
                elif nature == "fa":
                    #envoi annule
                    print("annulation de la reception du fichier")
                    if self.receptionFichier[contenu[0:2]]:
                       self.recuInfo("ff", "Reception {} annule \n".format(os.path.basename(self.receptionFichier[contenu[0:2]].name)))
                       self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
                       self.receptionFichier[contenu[0:2]].close()
                       #on supprime le fichier incomplet:
                       os.remove(self.receptionFichier[contenu[0:2]].name)
                       del self.receptionFichier[contenu[0:2]]

            elif categorie == "s":
                #infos sur le fonctionnement du serveur principal
                if nature == "sd":
                    #le serveur a ete ferme
                    self.serveurDeco()
                    
            elif categorie == "v":
                #infos liees au chat vocal
                if nature == "vs":
                    #un serveur vocal a ete cree
                    self.recuInfo("vs", "{} a cree un serveur vocal ({})".format(self.autresCo[emet], contenu))
                    self.ipServeurVoc = contenu
                    
                if nature == "vi":
                    #un client rejoint le chat vocal
                    self.recuInfo("vi", "{} a rejoint le chat vocal".format(self.autresCo[emet]))

                if nature == "vq":
                    #un client quitte le chat vocal
                    self.recuInfo("vq", "{} a quitte le chat vocal".format(self.autresCo[emet]))

                if nature == "vf":
                    #fermeture du serveur vocal
                    self.recuInfo("vf", "{} a ferme le serveur vocal".format(self.autresCo[emet]))
                    
            elif categorie == "p":
                if nature == "pi":
                    #nouveau plateau créé
                    print("nouveau plateau: {}\n".format(emet, contenu))
        else:
            print("Erreur: message illisible -> {}\n".format(msg))


    def recuInfo(self, nature, contenu):
        """signale une nouvelle information"""
        self.emit(SIGNAL("nouvelleInfo(QString, QString)"), QString.fromUtf8(nature), QString.fromUtf8(contenu))

    def recuMsg(self, emetteur, contenu):
        """signale un nouveau message texte pour le chat ecrit"""
        self.emit(SIGNAL("msgChat(QString, QString)"), QString.fromUtf8(emetteur), QString.fromUtf8(contenu))
        
    def envoi(self, nature, dest, msg, idFichier = ""):
        """envoie un message au serveur TCP
           - longueur du message (3 car)
           - nature du message (2 car)
           - exp: id de l'expediteur (2 car)
           - dest: id du destinataire (2 car)
           - msg: contenu du message  (999 car max)
           - un identifiant pour le fichier le cas echeant"""
        
        exp = self.idClient
        if self.client_connecte:
            try:
               if len(msg) <= 999:
                  if len(idFichier) == 0:
                     msg = unicode(msg)   
                     lg = "%003.f"%len(msg.encode('utf-8')) #la longueur apres encodage peut changer
                     txt = "{}{}{}{}{}".format(lg, nature, exp, dest, msg)
                     txt = txt.encode('utf-8')
                  else:
                     lg = "%003.f"%(len(msg)+2)
                     txt = "{}{}{}{}{}".format(lg, nature, exp, dest, idFichier)
                     txt = txt.encode('utf-8') + msg
                  
                  retour = len(txt)
                  self.cnn.sendall(txt)
   
               else:
                  self.recuInfo("  ","999 caracteres au max.")
                  retour = 0
                  
            except:
                retour = 0
                print("Envoi impossible")
        else:
            retour = ""
            print("Le client n'est pas connecte au serveur")
     
        return retour

    def envoiFichier(self, chemin, dest = "ac"):
        """intialise l'envoi d'un fichier"""
        if self.eFichier["id"] == "00":
           # on verifie si le fichier existe:
           fichier = None
           try:
               fichier = open(chemin, "rb")
           except:
               print("Le fichier '{}' est introuvable.".format(fichier))

           if not os.path.getsize(chemin) > 0:
               print("Envoi impossible - fichier vide")
               fichier.close()
               fichier  == None
              
           if fichier:
               #on demande un identifiant au serveur
               self.eFichier["fichier"] = fichier
               self.eFichier["chemin"] = chemin
               self.eFichier["dest"] = dest
               self.eFichier["annule"] = False
               self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(os.path.basename(chemin)), QString.fromUtf8("0"))
               print(self.eFichier)
               if dest == "ac":
                   for idC in self.autresCo:
                       self.destFichier[idC] = False
               else:
                   self.destFichier[dest] = False    
               self.envoi("f0","sa","")
                 
        else:
           self.annuleEnvoiFichier() 
          

    def envoiFichier_1(self, idFichier):
        """le fichier est pret a etre envoye, on attend confirmation des destinataires"""
        if len(idFichier) == 2:
           dest = self.eFichier["dest"]
           self.eFichier["id"] = idFichier
           nomFichier = os.path.basename(self.eFichier["chemin"])
           taille = os.path.getsize(self.eFichier["chemin"])
           print("{} a pour id {}\n".format(nomFichier, idFichier))

           #on previent les destinataires, et on leur transmet l'identifiant et le nom*taille du fichier
           print("En attente des destinataires...")
           self.recuInfo("fi", "{} - En attente des destinataires...".format(nomFichier))
           self.envoi("fi", dest, "{}{}".format(idFichier, nomFichier))
           
           while not self.eFichier["envoi"] and not self.eFichier["annule"]:
              time.sleep(0.001)
           if not self.eFichier["annule"]:    
              threading.Thread(None, self.envoiFichier_2, None, (), {}).start()
        else:
           print("Erreur envoi fichier: identifiant incorrect -> {}".format(idFichier))
           self.annuleEnvoiFichier()

            
    def pretEnvoiFichier(self, idClient):
        """signale un destinataire comme etant pret a recevoir le fichier ou le paquet de donnees"""
        pretEnvoi = False
        if self.eFichier["dest"] == "ac":
            self.destFichier[idClient] = True
            pretEnvoi = True
            #print("{} pret a recevoir le fichier".format(idClient))
            for idC in self.destFichier:
                if self.destFichier[idC] == False:
                    pretEnvoi = False
            #si tous les clients sont prets, on enclenche l'envoi du fichier sous forme de thread 
        else:
            if idClient == self.eFichier["dest"]:
                #print("{} pret a recevoir".format(idClient))
                pretEnvoi = True
        print("{} -> {}".format(idClient, pretEnvoi))        
        self.eFichier["envoi"] = pretEnvoi
            
                
    def envoiFichier_2(self):
        """thread d'envoi de fichier"""

        if self.eFichier["envoi"] and not self.eFichier["annule"]:
            idFichier = self.eFichier["id"]
            taille = os.path.getsize(self.eFichier["chemin"])
            nomFichier = os.path.basename(self.eFichier["chemin"])
            dest = self.eFichier["dest"]
            envoye = 0
            essais = 0
            
            #on envoie les donnees
            data = self.eFichier["fichier"].read(512)
            while len(data) == 512:
                if self.eFichier["annule"]:
                    #en cas d'annulation
                    break
                
                self.envoi("fd", dest, data, idFichier)
                envoye += len(data)
                print("{} / {}".format(int(envoye/1000), int(taille/1000)))
                
                #on attend confirmation de reception:
                self.eFichier["envoi"] = False
                if dest == "ac":
                   for idC in self.autresCo:
                       self.destFichier[idC] = False
                else:
                   self.destFichier[dest] = False  
                while not self.eFichier["envoi"]:
                    if self.eFichier["annule"]:
                        break
                    time.sleep(0.001)
                    essais += 1
                    if essais >= 1000:
                        #on renvoie un message pour demander confirmation  
                        self.envoi("fd", dest, b'', idFichier)
                        essais = 0
                        
                taux = str((100*envoye)/taille)
                self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8(taux))
                
                data = self.eFichier["fichier"].read(512)

            #pour dernier paquet on ajoute au drapeau: "%003.f"%len(paquet)   
            #on signale que c'est le dernier paquet et on ajoute 3 caracteres pour en specifier la taille:

            if not self.eFichier["annule"]:
                self.envoi("ff", dest, data, idFichier)
                envoye += len(data)
                print("{} / {}".format(int(envoye/1000), int(taille/1000)))
                
                self.eFichier["envoi"] = False
                while not self.eFichier["envoi"]:
                    if self.eFichier["annule"]:
                        break
                    time.sleep(0.001)
                    essais += 1
                    if essais >= 1000:
                        #on renvoie un message pour demander confirmation
                        print("on redemande confirmation")
                        self.envoi("fd", dest, b'', idFichier)
                        essais = 0
                taux = str((100*envoye)/taille)
                self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8(taux))
                
                self.envoi("f1", "sa", "{}".format(idFichier))
                self.recuInfo("ff", "- {} a bien ete envoye -".format(nomFichier))
                self.emit(SIGNAL("inserImg(QString, QString)"), QString.fromUtf8(self.idClient), QString.fromUtf8(self.eFichier["chemin"]))
                print("\n- Fichier envoye -")
                self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule": False}
            else:
                self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule": True}
        else:
            print("Erreur envoi fichier: signal serveur non-recu -> {}".format(self.eFichier["id"]))
            self.annuleEnvoiFichier()

        

    def annuleEnvoiFichier(self):
        """annule l'envoi d'un fichier"""
        print("Envoi annule")
        self.recuInfo("fa", "- Envoi du fichier annule -")
        self.envoi("fa", self.eFichier["dest"], "{}".format(self.eFichier["id"]))
        self.eFichier["annule"] = True
        self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))

    def nouveauFichier(self, idFichier, nomFichier):
        """cree le fichier a recevoir - le renomme si un fichier portant ce nom existe deja - retourne le chemin complet"""
        k = 1
        tmp = nomFichier
        retour = ""
        try:
           while os.path.isfile(self.repReceptionFichiers+tmp):     
              k += 1
              tmp = nomFichier.split(".")[0]+str(k)+"."+nomFichier.split(".")[1]
              if k == 100:
                  tmp = ""
                  break
           if len(tmp) > 0:     
              self.receptionFichier[idFichier] = open((self.repReceptionFichiers + tmp), "wb")
              retour = tmp
        except:
           print("Impossible de creer le fichier")
        return retour

    def serveurDeco(self):
        """le serveur a ferme - on affiche a nouveau l'ecran de connexion"""
        #on annule les envois de fichier en cours
        if self.eFichier["fichier"] != None:
            self.eFichier["annule"] = True
            self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
        #on annule les receptions de fichiers en cours
        for idFichier in self.receptionFichier:
            print("{} - reception annulee".format(self.receptionFichier[idFichier].name))
            self.receptionFichier[idFichier].close()
            os.remove(self.receptionFichier[idFichier].name)
            self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
        self.receptionFichier = {}  
        
        self.recuInfo("sd", "(!) Le serveur a mis la clef sous la porte (!)")
        self.cnn.close()
        self.client_connecte = False
        self.serveur_lance = False
        time.sleep(0.01)
        self.show()
        self.msg("")

    def recupParamCo(self):
        """recupere les derniers parametres de connexion enregistres s'il existent"""
        try:
            with open("parametresCo", 'rb') as input:
                dico = pickle.load(input)
                self.pseudo = dico["pseudo"]
                self.port = dico["port"]
                self.ip = dico["ip"]
                self.repReceptionFichiers = dico["repReceptionFichiers"] 
            retour = dico
            #{"pseudo": "", "port" : 6660, "ip": "", "repReceptionFichiers" : "C:\\"}
            input.close()
        except IOError:
            retour = ("Erreur: parametresCo introuvable")

        return retour        

    def sauverParamCo(self):
        """sauvegarde les parametres de connexion pour une prochaine utilisation"""
        with open("parametresCo", 'wb') as output:
             dico = {"pseudo": str(self.pseudo), "port" : int(self.port), "ip": str(self.ip), "repReceptionFichiers" : str(self.repReceptionFichiers)}
             pickle.dump(dico, output, -1)
        output.close()
        chaine = "parametres sauvegarde."

        return chaine

    def fermer(self):
        """fermeture de la connexion, et du serveur le cas echeant"""
        if self.client_connecte:
           try:
              self.envoi("cd", "sa", "") 
           except:
              print("impossible de prévenir le serveur de la deco")
           self.client_connecte = False
           self.cnn.close()
           if self.eFichier["fichier"] != None:
               self.eFichier["annule"] = True
           time.sleep(0.001)
           print("\n"+self.sauverParamCo())
           
        if self.serveur_connecte:
           self.s.stop()
           self.serveur_connecte = False   
           time.sleep(0.001)
           
        self.close()
        
    def closeEvent(self, event):
        """sur fermeture de la fenetre"""
        if not self.client_connecte:
            self.fermer() 

class EcranChat(QGroupBox):
    """interface comprenant: chat ecrit, fenetre d'infos, lancer de des, echange de fichiers, lancement du chat vocal"""
    def __init__(self, connexion, parent=None):
        """initialisation de la fenetre"""
        super (EcranChat, self).__init__(parent)
        self.co = connexion
        self.connecte = True
        self.estServeurVoc = False
        self.estClientVoc = False
        self.createWidgets()

    def createWidgets(self):
        """construction de l'interface"""
        #construction de l'interface
        self.ui = Ui_chat()
        self.ui.setupUi(self)

        #connexion des commandes
        self.connect(self.ui.inChat, SIGNAL("returnPressed()"), self.envoiMsg)
        self.connect(self.ui.d20, SIGNAL("clicked()"), self.d20)
        self.connect(self.ui.d100, SIGNAL("clicked()"), self.d100)
        self.connect(self.ui.inJetDes, SIGNAL("returnPressed()"), self.autreJet)
        self.connect(self.ui.envoiFichier, SIGNAL("clicked()"), self.envoyerfichier) 
        self.connect(self.ui.repReceptionFichiers, SIGNAL("clicked()"), self.repReception)
        self.connect(self.ui.listFichiers, SIGNAL("itemDoubleClicked(QTreeWidgetItem*, int)"), self.ouvrirFichier)
        #self.connect(self.ui.chatVoc, SIGNAL("clicked()"), self.chatVoc)
        #self.connect(self.ui.creerServeurVoc, SIGNAL("clicked()"), self.creerServeurVoc)

        #reception des signaux self.emit(SIGNAL("majAffichage()"))
        self.connect(self, SIGNAL("msgChat(QString, QString)"), self.ajoutChat)
        self.connect(self.co, SIGNAL("msgChat(QString, QString)"), self.ajoutChat)
        self.connect(self, SIGNAL("nouvelleInfo(QString, QString)"), self.ajoutInfo)
        self.connect(self.co, SIGNAL("nouvelleInfo(QString, QString)"), self.ajoutInfo)
        self.connect(self, SIGNAL("initRecFichier(QString, QString)"), self.afficheReception)
        self.connect(self.co, SIGNAL("initRecFichier(QString, QString)"), self.afficheReception)
        self.connect(self, SIGNAL("inserImg(QString, QString)"), self.inserImgChat)
        self.connect(self.co, SIGNAL("inserImg(QString, QString)"), self.inserImgChat)
        self.connect(self, SIGNAL("initEnvFichier(QString, QString)"), self.afficheEnvoi)
        self.connect(self.co, SIGNAL("initEnvFichier(QString, QString)"), self.afficheEnvoi)
        self.connect(self, SIGNAL("majAffichage()"), self.majStatut)
        self.connect(self.co, SIGNAL("majAffichage()"), self.majStatut)        
        self.majStatut()
        
    def msg(self, txt):
        """affichage d'un message informatif sous forme de label"""
        self.ui.txt_msg.setText(QString.fromUtf8(txt))
        QApplication.processEvents()

    def ajoutChat(self, emetteur, msg):
        """ajoute une nouvelle ligne au chat ecrit"""
        emetteur = str(emetteur)
        if emetteur == self.co.idClient:
            txt = "<font color=\"blue\">{} : </font> {}".format(self.co.pseudo, msg)
        else:
            pseudo = self.co.autresCo["{}".format(emetteur)]
            txt = "<font color=\"green\">{} : </font> {}".format(pseudo, msg)
            
        txt = QString.fromUtf8(txt)
        item = QListWidgetItem(self.ui.listAffichage)
        self.ui.listAffichage.addItem(item)
        label = QLabel()
        label.setWordWrap(True)
        label.setText(txt)
        item.setSizeHint(QSize(120, label.heightForWidth (self.ui.listAffichage.width()) + 5))
        self.ui.listAffichage.setItemWidget(item, label)
        QApplication.processEvents()

    def ajoutInfo(self, nature, msg):
        """ajoute une nouvelle ligne a la liste des evenements"""
        #couleur selon nature de l'info:
        if nature[:1] == "c":
            txt = "<font color=\"green\">{}</font>".format(msg)
        elif nature == "id":
            txt = "<font color=\"red\">{}</font>".format(msg)
        elif nature[:1] == "f":
            txt = "<font color=\"blue\">{}</font>".format(msg)    
        else:
            txt = msg

        txt = QString.fromUtf8(txt)         
        item = QListWidgetItem(self.ui.listEvenement)
        self.ui.listEvenement.addItem(item)
        label = QLabel()
        label.setWordWrap(True)
        label.setText(txt)
        item.setSizeHint(QSize(120, label.heightForWidth (self.ui.listEvenement.width()) + 5))
        self.ui.listEvenement.setItemWidget(item, label)
        QApplication.processEvents()

    def inserImgChat(self, emet, fichier):
        """insere une image dans le QListWidget chat"""
        emet = str(emet)
        fichier = str(fichier)
        try: 
           typeFichier = fichier.split(".")[len(fichier.split("."))-1]
        except:
           typeFichier = "" 

        if typeFichier.lower() in ["png", "jpeg", "jpg"]:
             #si c'est une image, on essaie de l'inserer dans le chat
             print("ajout d'une image au chat : " + fichier)
             self.ajoutChat(str(emet), "<img src=\"{}\"/>".format(fichier))
               
    def envoiMsg(self):
        """envoie un message pour le chat ecrit"""
        msg = self.ui.inChat.text()
        self.co.envoi("m ", "tc", msg)
        self.ui.inChat.clear()
        QApplication.processEvents()

    def lancerD(self, expr):
        """fonction de lancer de des"""
        res, detail = jet(expr)
        if res > 0:
            txt = "{}: {}   ({})  [{}]".format(self.co.pseudo, res, detail, expr)
            self.co.envoi("id", "tc", txt)
        else:
            self.ajoutInfo("id", "mmmhh, pas bon le jet")
        return res
             
    def d20(self):
        """lance un D20"""
        self.lancerD("1d20")
        
    def d100(self):
        """lance un D100"""
        self.lancerD("1d100")

    def autreJet(self):
        """lance un jet personnalise"""
        expr = str(self.ui.inJetDes.text())
        retour = self.lancerD(expr)
        self.ui.inJetDes.clear()

    def envoyerfichier(self):
        """selectionne et envoie un fichier ou annule l'envoi en cours s'il existe"""
        if self.co.eFichier["id"] == "00":
           fichier = QFileDialog.getOpenFileName(
                       self, 
                       "Selectionnez un fichier a envoyer", 
                       "c:\\", 
                       "")
           if len(str(fichier)) > 0:
              self.co.envoiFichier(str(fichier))
        else:
           self.co.annuleEnvoiFichier()
           
    def ouvrirFichier(self):
        """ouvre un fichier depuis la liste des fichiers recus/envoyes"""
        item = self.ui.listFichiers.currentItem()
        eR = item.text(0)
        taux = item.text(1)
        nom = item.text(2)
        print(nom)
        if eR == "R":
            if taux == "ok":
                try:
                    chemin = "{}\\{}".format(self.co.repReceptionFichiers, nom)
                    subprocess.Popen(chemin, shell=True, stdout=subprocess.PIPE)
                except:
                    print("impossible d'ouvrir le fichier")

        
    def repReception(self):
        """permet de choisir son repertoire de reception des fichiers"""
        dossier = QFileDialog.getExistingDirectory(self)
        if dossier[len(dossier)-1:] != "\\":
            dossier += "\\"
        self.co.repReceptionFichiers = str(dossier)
        self.majStatut()

    def afficheReception(self, fichier, taux):
        """ajoute une ligne a la liste des fichiers en cours de reception"""
        fichier = str(fichier)
        taux = str(taux)
        if len(fichier) > 0:
            self.ligneRFichier = QTreeWidgetItem(self.ui.listFichiers, ["R", taux, fichier])
        elif len(taux) > 0:
            if taux != self.ligneRFichier.text(1): 
                self.ligneRFichier.setText(1, taux)                   

    def afficheEnvoi(self, fichier, taux):
        """ajoute une ligne a la liste des fichiers en cours d'envoi"""
        fichier = str(fichier)
        taux = str(taux)
        if len(fichier) > 0:
            self.ligneEFichier = QTreeWidgetItem(self.ui.listFichiers, ["E", taux, fichier])
        elif len(taux) > 0:
            if taux != self.ligneEFichier.text(1): 
                self.ligneEFichier.setText(1, taux)
            
    def majStatut(self):
        """met a jour la ligne de statut au pied de l'interface"""
        if self.co.serveur_connecte:
            txt = "Serveur : Oui"
        else:
            txt = "Serveur : Non"
        txt += " \ Pseudo : {}".format(self.co.pseudo)
        if self.estServeurVoc:
            txt += " \ Serveur vocal"
            
        if self.estClientVoc:
            txt += " \ connecte au chat vocal"
            
        self.msg(txt)
        self.ui.txt_repReception.setText(QString.fromUtf8("Fichiers recus : '{}'".format(self.co.repReceptionFichiers)))
        QApplication.processEvents()

        
    def creerServeurVoc(self):
        """cree un serveur vocal"""
        if not self.estServeurVoc:
            self.sVoc = ServeurVoc(6660, 1024)
            txt = self.sVoc.creer()
            self.co.info("vs", txt)
            if self.sVoc.serveur_lance:
                self.co.envoi("vs","ac","{}".format(self.co.ipClient))
                self.estServeurVoc = True
                self.majStatut()
        else:
            self.fermerServeurVoc()
            

    def fermerServeurVoc(self):
        """ferme le serveur vocal"""
        txt = self.sVoc.stop()
        self.co.recuInfo("vs", txt)
        if not self.sVoc.serveur_lance:
            self.c.envoi("vf","ac","")
            self.estServeurVoc = False
            self.majStatut()
        
    def chatVoc(self):
        """connexion au chat vocal"""
        if not self.estClientVoc:
             self.cVoc = ClientVoc()
             txt = self.cVoc.creer(self.co.pseudo, self.c.R.ipServeurVoc)
             if self.cVoc.connecte:
                 self.ajoutInfo("vi "+txt)
                 self.co.envoi("vi","ac","")
                 self.estClientVoc = True
                 self.majStatut()
        else:
            self.quitterChatVoc()

    def quitterChatVoc(self):
        """deconnexion du chat vocal"""
        if self.estClientVoc:
            txt = self.cVoc.stop()
            self.co.recuInfo("vq", txt)
            self.co.envoi("vq","ac","")
            self.estClientVoc = False
            self.majStatut()            

    def closeEvent(self, event):
        """sur fermeture de la fenetre"""
        if self.estClientVoc:
            self.cVoc.stop()
        if self.estServeurVoc:
            self.sVoc.stop()
        self.co.fermer()
        time.sleep(0.01)
        self.connecte = False    
        self.close()             
        
if __name__ == "__main__":
    app = QApplication(sys.argv)
    connexion = EcranConnexion()
    connexion.show()
    r = app.exec_()
    if r == 0 and connexion.client_connecte:
        #si pas d'erreur et client connecte, on ouvre l'interface principale
        ecranChat = EcranChat(connexion)
        ecranChat.show()
        r = app.exec_()
        sys.exit(r)
        

    


    
    
    
