import asyncore
import socket
import constants as C

HOST = C.REMOTE_HOST
PORT = C.REMOTE_PORT

class ChatServer(asyncore.dispatcher):
    """Receive and forward chat messages
    
    When a new connection is made we spawn a dispatcher for that
    connection.
    """
    ADDRESS_FAMILY = socket.AF_INET
    SOCKET_TYPE = socket.SOCK_STREAM
    def __init__(self, host, port):
        self.map = {}
        self.address = (host,port)
        self.clients = []
        asyncore.dispatcher.__init__(self, map=self.map)
    
    def serve(self):
        """Bind to socket and start asynchronous loop"""
        self.create_socket(self.ADDRESS_FAMILY, self.SOCKET_TYPE)
        self.bind(self.address)
        print("ChatServer bound to %s %s"%self.address)
        self.listen(1)
        asyncore.loop(map=self.map)
    
    def writable(self):
        return False
    
    def readable(self):
        return True
    
    def newMessage(self, data, fromWho):
        """Put data in all clients' buffers"""
        for client in self.clients:
            client.buffer = client.buffer + data
    
    def handle_accept(self):
        """Deal with newly accepted connection"""
        (connSock, clientAddress) = self.accept()
        print("New connection accepted from %s %s"%clientAddress)
        self.clients.append(ChatHandler(connSock, self.map, self))

class ChatHandler(asyncore.dispatcher):
    def __init__(self, sock, map, server):
        self.server = server
        self.buffer = ''
        asyncore.dispatcher.__init__(self, sock, map)
    
    def writable(self):
        return len(self.buffer) > 0
    
    def readable(self):
        return True
    
    def handle_read(self):
        """Notify server of any new incoming data"""
        data = self.recv(4096)
        if data:
            self.server.newMessage(data, self)
    
    def handle_write(self):
        """send some amount of buffer"""
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]

if __name__=='__main__':
    if HOST is None:
        HOST = raw_input('Host: ')
    if PORT is None:
        PORT = int(raw_input('Port: '))
    s = ChatServer(HOST, PORT)
    s.serve()