
# This is built as a subclass instead of an extension so we can define the
# class variable FuncDict and so we can import DCSubatomicType at the top
# of the file rather than every time we call the putArg function.

from pandac.PandaModules import *
# Import the type numbers
from pandac.DCSubatomicType import *

class PyDatagram(Datagram):

    # This is a little helper Dict to replace the huge <if> statement
    # for trying to match up datagram subatomic types with add funtions
    # If Python had an O(1) "case" statement we would use that instead
    FuncDict = {
        STInt8  : (Datagram.addInt8, int),
        STInt16 : (Datagram.addInt16, int),
        STInt32 : (Datagram.addInt32, int),
        STInt64 : (Datagram.addInt64, int),
        STUint8  : (Datagram.addUint8, int),
        STUint16 : (Datagram.addUint16, int),
        STUint32 : (Datagram.addUint32, int),
        STUint64 : (Datagram.addUint64, int),
        STFloat64 : (Datagram.addFloat64, None),
        STString : (Datagram.addString, None),
        STBlob : (Datagram.addString, None),
        STBlob32 : (Datagram.addString32, None),
        }

        
    addChannel = Datagram.addUint64
    
    def putArg(self, arg, subatomicType, divisor=1):
        if (divisor == 1):
            funcSpecs = self.FuncDict.get(subatomicType)
            if funcSpecs:
                addFunc, argFunc = funcSpecs
                if argFunc:
                    arg = argFunc(arg)
                addFunc(self, arg)
            # Ok, arrays are not handled by the FuncDict yet
            elif subatomicType == STInt8array:
                self.addUint16(len(arg))
                for i in arg:
                    self.addInt8(int(i))
            elif subatomicType == STInt16array:
                self.addUint16(len(arg) << 1)
                for i in arg:
                    self.addInt16(int(i))
            elif subatomicType == STInt32array:
                self.addUint16(len(arg) << 2)
                for i in arg:
                    self.addInt32(int(i))
            elif subatomicType == STUint8array:
                self.addUint16(len(arg))
                for i in arg:
                    self.addUint8(int(i))
            elif subatomicType == STUint16array:
                self.addUint16(len(arg) << 1)
                for i in arg:
                    self.addUint16(int(i))
            elif subatomicType == STUint32array:
                self.addUint16(len(arg) << 2)
                for i in arg:
                    self.addUint32(int(i))
            elif subatomicType == STUint32uint8array:
                self.addUint16(len(arg) * 5)
                for i in arg:
                    self.addUint32(int(i[0]))
                    self.addUint8(int(i[1]))
            else:
                raise Exception("Error: No such type as: " + str(subatomicType))
        else:
            funcSpecs = self.FuncDict.get(subatomicType)
            if funcSpecs:
                # argFunc is only used if divisor == 1
                addFunc, argFunc = funcSpecs
                addFunc(self, int(round(arg * divisor)))
            # Ok, arrays are not handled by the FuncDict yet
            elif subatomicType == STInt8array:
                self.addUint16(len(arg))
                for i in arg:
                    self.addInt8(int(round(i*divisor)))
            elif subatomicType == STInt16array:
                self.addUint16(len(arg) << 1)
                for i in arg:
                    self.addInt16(int(round(i*divisor)))
            elif subatomicType == STInt32array:
                self.addUint16(len(arg) << 2)
                for i in arg:
                    self.addInt32(int(round(i*divisor)))
            elif subatomicType == STUint8array:
                self.addUint16(len(arg))
                for i in arg:
                    self.addUint8(int(round(i*divisor)))
            elif subatomicType == STUint16array:
                self.addUint16(len(arg) << 1)
                for i in arg:
                    self.addUint16(int(round(i*divisor)))
            elif subatomicType == STUint32array:
                self.addUint16(len(arg) << 2)
                for i in arg:
                    self.addUint32(int(round(i*divisor)))
            elif subatomicType == STUint32uint8array:
                self.addUint16(len(arg) * 5)
                for i in arg:
                    self.addUint32(int(round(i[0]*divisor)))
                    self.addUint8(int(round(i[1]*divisor)))
            else:
                raise Exception("Error: type does not accept divisor: " + str(subatomicType))
