# -*-coding:Latin-1 -*
"""Serveur UDP de chat vocal"""
import socket
import time
import threading
import os

port = 6660
taille_paquet = 1024


class DebitMetre(threading.Thread):
    """debitmetre permettant de mesurer le debit d'emission/reception du serveur"""
    def __init__(self, taille_paquet):
        """création du serveur vocal"""
        threading.Thread.__init__(self)
        self.mesureEnvoi = 0
        self.mesureReception = 0
        self.debitEmission = 0.00
        self.debitReception = 0.00
        #si oui, affiche les resultats chaque seconde:
        self.affichage = True
        
    def envoi(self, taille_paquet):
        """pour signaler l'envoi d'un paquet"""
        self.mesureEnvoi += taille_paquet

    def reception(self, taille_paquet):
        """pour signaler la reception d'un paquet"""
        self.mesureReception += taille_paquet

    def run(self):
        """mesure le volume en octets qui transite chaque seconde"""
        self.lance = True
        t0 = time.time()
        while self.lance:   
            delta = time.time() - t0
            if delta >= 1:
                self.debitEmission = self.mesureEnvoi / delta
                self.mesureEnvoi = 0
                self.debitReception = self.mesureReception / delta
                self.mesureReception = 0
                t0 = time.time()
                if self.affichage:
                    print(self)

    def __repr__(self):
        """affiche les derniers debits mesures (en ko/s)"""
        retour = "** Reception: {} ko/s ** -> Emission: {} ko/s **"\
                  "".format((self.debitEmission * 0.001), (self.debitReception * 0.001))   
        return retour    

    def stop(self):
        """Fermeture du fil debitmetre"""    
        self.lance = False

        
class Serveur(threading.Thread):
    """serveur UDP dedie au chat vocal"""
    def __init__(self, port, taille_paquet):
        """création du serveur vocal"""
        threading.Thread.__init__(self)
        self.serveur_lance = False
        #pour gerer le verrouillage des threads
        
        self.connectes = []
        self.taille_paquet = taille_paquet
        self.port = port
        #debitmetre pour mesurer l'emission
        self.dM = DebitMetre(taille_paquet)
        self.dM.affichage = False
        
    def creerServeur(self):
        """creation d'une entree serveur UDP"""
        try:
           self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
           self.socket.bind(('', self.port))
           print("Le serveur vocal ecoute a present sur le port {}\n".format(self.port))
           self.serveur_lance = True
           self.dM.start()
        except IOError, e:
            if e.errno==10048:
               print("\nUne instance du serveur est déja lancée")
            else:   
               print("\nechec de lancement du serveur")       

    def nouveauClient(self, adresse):
        """ajoute un nouveau client a la liste des connectes"""
        self.connectes.append(adresse)
        print("Nouveau client connecte: {}\n)".format(adresse))

    def supprimerClient(self, adresse):
        """ajoute un nouveau client a la liste des connectes"""
        self.connectes.remove(adresse)
        print("Client deconnecte: {}\n)".format(adresse)) 

    def run(self):
        """boucle de fonctionnement du serveur"""
        while self.serveur_lance:
            #on recoit les donnees envoyees 
            try:
               data, adresse = self.socket.recvfrom(self.taille_paquet)
               self.dM.reception(len(data))
            except IOError, e:
               if e.errno == 10022:  
                 # print("erreur de reception {}".format(adresse))
                 #self.supprimerClient(adresse)
                  time.sleep(0.02)
               else:
                  print("erreur {}".format(e.errno)) 

            if data:
                if not adresse in self.connectes:
                    #l'adresse n'est pas dans la liste: on l'ajoute aux connectes
                    self.nouveauClient(adresse)
                    #on lui envoie les parametres de la co?
                    
                else:
                    for dest in self.connectes:
                        if dest != adresse:
                            #le client ne recoit pas ses propres donnees
                            self.socket.sendto(data , dest)
                            self.dM.envoi(len(data))
                            #tmp = "{} -> {}".format(len(data), adresse)

        
    def stop(self):
        """Fermeture du serveur"""
        self.dM.stop()
        self.serveur_lance = False
        self.socket.close()
        print("\nFermeture du serveur")

        
### fil principal ###
if __name__ == "__main__":
   # si lancement direct:
   thS = Serveur(port, taille_paquet)
   thS.creerServeur()
   thS.start()
   os.system("pause")
   thS.stop()
   time.sleep(1)
   

