#!/usr/bin/env python
import threading
import socket
import sys
import os
import signal

class ClientThread(threading.Thread):

    def __init__(self,cl_socket,group):
        threading.Thread.__init__(self)
        self.cl_socket=cl_socket
        self.f=self.cl_socket.makefile()
        self.group=group
        self.tell_lock=threading.Lock()

    def run(self):
        while True:
            self.f.write('Name:')
            self.f.flush()
            self.name=self.f.readline().strip()
            if self.name:
                break
        self.group.add(self)
        for line in self.f:
            self.group.tell_others(self,line)
        self.group.remove(self)
        self.f.close()
        # self.cl_socket.shutdown(socket.SHUT_RDWR)
        self.cl_socket.close()

    
    def tell(self,what):
        self.tell_lock.acquire()
        self.f.write(what)
        self.f.flush()
        self.tell_lock.release()

class ClientGroup(object):

    def __init__(self):
        self.clients=[]
        self.clients_lock=threading.Lock()

    def add(self,client):
        self.clients_lock.acquire()
        self.clients.append(client)
        self.clients_lock.release()
        self.tell_others(client,'* entered the room *\n')

    
    def remove(self,client):
        self.clients_lock.acquire()
        self.clients.remove(client)
        self.clients_lock.release()
        self.tell_others(client,'* left the room *\n')

    def tell_others(self,client,line):
        what=client.name+"> "+line
        for other in self.clients:
            other.tell(what)
    
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# Naviazeme ho na port 2222 pre vsetky lokalne adresy
s.bind(('',2222))
# Najviac 5 spojeni bude cakat vo fronte
s.listen(5)

# Toto je kvoli tomu, aby nam nezostavali zombie 
# procesy a neprerusoval nas signal SIGCHLD
signal.signal(signal.SIGCHLD,signal.SIG_IGN)

group=ClientGroup()
try:
    while True:
        connected_socket,address=s.accept()
        print 'Connected by',address
        client=ClientThread(connected_socket,group)
        client.setDaemon(True)
        client.start()
        del client
except KeyboardInterrupt:
    pass
s.shutdown(socket.SHUT_RDWR)
s.close()

