import socket
import threading
import select
import os
import time
from MessageBuffer import *

class MessageIO(threading.Thread):
    """
    Handles communication of messages to and from the server.
    It will use a message handler to send messages it receives.
    """

    def __init__(self, messageHandler):
        """
        attempt to connect to the server
        """
        super(MessageIO, self).__init__()
        
        self.isConnected = False
        
        self.setMessageHandler(messageHandler)        
        self.messageBuffer = MessageBuffer()

    
    def connect(self, host, port):
        """
        attempts to connect via TCP to host and port
        if successful, it will start our listening thread
        """
        self.host = host
        self.port = port
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.socket.connect( (host, port) )
        
        self.isConnected = True
        
        # superclass method that ultimately calls our run method
        self.start()        
    
    def sendMessage(self, message):
        """
        sends a serialized version of the message over the socket
        """
        if self.isConnected:
            self.socket.send(message.getBinary())            

    def setMessageHandler(self, messageHandler):
        """
        the method our class will call when it has a full message to send
        """
        self.messageHandler = messageHandler

    def stopListening(self):
        """
        inform the select() that we want to stop listening
        """
        if self.isConnected:        
            self.controlw.write('1')
            self.controlw.flush()
        
    def run(self):
        """
        the main listen loop
        opens a pipe so the loop can be controlled by writing values to
        self.controlw (file-descriptor) see stopListening() for example
        """

        r, w = os.pipe()
        
        self.controlr = os.fdopen(r)
        self.controlw = os.fdopen(w, 'w')
                
        self.quitRunning = 0
        
        while not self.quitRunning:
            inReady, outReady, exceptReady = select.select( [self.socket, self.controlr], [], [self.socket] )						

            for i in inReady:
                if i == self.controlr:
                    val = self.controlr.read(1)
                    if val == '1':
                        self.quitRunning = 1
                                
                else:
                    data = self.socket.recv(16384)
                    #print data
                    #print "data len", len(data)
                    
                    # check to see if error occurs?
                    if len( data ) <= 0:
                        self.quitRunning = 1
                    
                    remainingData = data
                    
                    parsing = 1
 
                    while parsing and len(remainingData) > 0:
                        remainingData = self.messageBuffer.processUntilNextMessage(remainingData)
                    
                        if self.messageBuffer.hasCompleteMessage():
                            self.messageHandler( self.messageBuffer.getMessage() )
                            
                            self.messageBuffer.reset()
                            
                        else:
                            parsing = 0
                        

                    # append to message buffer
                            
            if exceptReady:
                self.quitRunning = 1
        
        self.controlw.close()
        self.controlr.close()
        