import OSCUtilities

class MessageBuffer:
    """
    Handles buffering OSC messages.
    
    Currently the format is:
    
    offset | name
    ================
    0x0000 | header
    0x0004 | data

    where header is 4 bytes indicating the length of the data    
    """
    
    def __init__(self):
        self.headerSize = 4
        
        self.reset()
                
    def sizeOfIncomingMessage(self):
        """
        Returns the size of the message we are currently reading
        """
        return self.messageHeader

    def setHasMessageHeader(self, val):
        """
        update the message header flag
        """
        self.hasMessageHeader = val
            
    def reset(self):
        """
        Reset message state
        """
        self.buffer = ''
        self.bufferSize = 0
        self.setHasCompleteMessage(False)
        self.messageHeader = None
        self.hasMessageHeader = False  
        self.header = ''
        
        
    def processUntilNextMessage(self, data):            
        """
        data - input data stream
        
        identifies message headers and uses this information to obtain
        a complete message from the stream - it returns any remaining / unprocessed
        data to the caller
        """
        dataLen = len(data)
        
        # check to see if we have a message header    
        if not self.hasMessageHeader:
            # we do not, so let's assume the first 4 bytes of
            # this data stream represents the header
            bytesToFinishHeader = self.headerSize - len( self.header )
                
            if dataLen >= bytesToFinishHeader:
                # we have enough data to finish the header
                self.header += data[0:bytesToFinishHeader]                
                self.messageHeader, blah = OSCUtilities.readInt(self.header)
                self.setHasMessageHeader(True)

                data = data[bytesToFinishHeader:]
            else:    
                #print "PARTIAL HEADER ====================="
                # we do not have enough
                # just append what we have
                self.header += data
                data = ''
                    
                #print "MessageHeader:", self.messageHeader
                return ''
                
                        
        incomingDataSize = len(data)
        
        #print "incomingDataSize:", incomingDataSize
        
        bytesRemainingInMessage = self.sizeOfIncomingMessage() - self.bufferSize 
        
        if incomingDataSize >= bytesRemainingInMessage:
            # we have enough to complete a message            
            self.appendToBuffer( data[0:bytesRemainingInMessage] )
            self.setHasCompleteMessage(True)
            
            self.bufferSize += bytesRemainingInMessage
            
            return data[bytesRemainingInMessage:]        

        else:
            self.appendToBuffer( data )
            self.bufferSize += incomingDataSize

            return []

                
    def setHasCompleteMessage(self, val):
        """
        sets the _hasCompleteMessage flag
        """
        self._hasCompleteMessage = val

    def hasCompleteMessage(self):
        """
        informs the caller whether the message is complete
        """
        return self._hasCompleteMessage

    def appendToBuffer(self, data):
        """
        append data to our buffer
        """
        self.buffer += data
        
    def getMessage(self):
        """
        get the data in our buffer
        """
        return self.buffer