###############################################################################
# Custom classes for Surgical Log
###############################################################################
from collections import deque
from os import path
import os
import re
import serial #@UnresolvedImport
import threading
import time
import wx

##Global constants
PCO2_ITEM_DECK_MAX_LEN = 10
PCO2_SERIAL_BUFFER_SIZE = 6
DEBUG=0

class mouseClass():
    def __init__(self, weight=0, sex=0, inType="", dob=wx.DateTime()):
        self.weight = weight
        self.sex = sex
        self.type = inType
        self.dob = dob
        
class expClass():
    def __init__(self,date=wx.DateTime(), comments="", drugList=[], mouseTypes=[], mouse=mouseClass()):
        self.date = date
        self.comments = comments
        self.drugList = drugList
        self.mouseTypes = mouseTypes;
        self.mouse = mouse
    
    def writeHeader(self):
        header =u'Date: %s\n'%self.date.Format("%a %b %d %Y")
        header+="\n"
        header+="Mouse %s"%self.mouse.type
        if self.mouse.sex==0:
            header+=" male"
        else:
            header+=" female"
        header+="\n"
        header+="DoB:"
        if self.mouse.dob.IsValid():
            age = self.date - self.mouse.dob
            header+=self.mouse.dob.Format(" %a %b %d %Y")
            header+=" (%d days)"%age.GetDays()
        header+="\n"
        header+="Weight:"
        if self.mouse.weight>0:
            header+=" %dg"%self.mouse.weight
        header+="\n"
        header+="\n"
        header+="Drugs:\n"
        for drug in self.drugList:
            header+=drug.printForList()
            header+="\n"
        header+="\n"
        header+="Comments:\n"
        header+=self.comments
        header+="\n"
        return header

class drugClass():
    def __init__(self, name, dose):
        self.name = name
        self.dose = dose
    
    def printForList(self):
        return "%-12s| %4d uL"%(self.name,self.dose)

class dataLogClass():
    def __init__(self, line):
        if len(line)<=0 or not isinstance(line, str):
            raise TypeError, "argument must be a string of length > 0"
            return False
        
        strList = line.split(',')
        if len(strList)<=0:
            raise ValueError, "Cannot parse line"
            return False
        
        try:
            date = strList[0]+strList[1]+strList[2]
            date = date.strip('"')
            self.dateTime = wx.DateTime()
            self.dateTime.ParseFormat(date,'%A %B %d %Y %I:%M:%S %p')
            self.pulseDist = float(strList[3])
            self.breathDist = float(strList[4])
            self.heartRate = float(strList[5])
            self.sp02 = float(strList[6])
            self.breatRate = float(strList[7])
        except Exception, theException:
            print theException #DEBUG
            raise ValueError, "Cannot parse line"
            return False
        
    def printLine(self):
        ret  = "%s\t"%self.dateTime.Format("%H:%M")
        ret += "%5.0f bpm | "%self.heartRate
        ret += "%4.1f %% | "%self.sp02
        ret += "%4.1f um | \n"%self.pulseDist
        return ret

class diagLogClass():
    def __init__(self, inFile):
        if inFile==None:
            raise SyntaxError, "Must provide a valid inFile"
            return False
        
        self.file = inFile
        self.lines = []
        inFile.seek(0) #reset the pointer to the beginning of the inFile
        for _ in (1,2,3):
            inFile.readline() #skips the three fist header lines
        
        self.startDataPos = inFile.tell()
        self.currentPos = self.startDataPos
    
    def printNext(self):
        fileName = self.file.name
        filePos = self.file.tell()
        self.file.close()
        self.file = open(fileName,'r')
        self.file.seek(filePos)
        ret = u''
        for line in self.file:
            try:
                temp = dataLogClass(line)
                ret += temp.printLine()
                self.lines.append(temp)
            except Exception, theException:
                print theException #DEBUG
                pass
        return ret

class surgicalLogConfigClass():
        def __init__(self, baseFolder=os.getcwd(), createFolder=True, updateReg=True, autoSave=True, logFileName="SurgicalLog.txt"):
            self.setBaseFolder(baseFolder)
            self.setCreateFolder(createFolder)
            self.setUpdateReg(updateReg)
            self.setAutoSave(autoSave)
            self.setLogFileName(logFileName)

        def getLogFileName(self):
            return self.__logFileName


        def setLogFileName(self, value):
            self.__logFileName = value


        def delLogFileName(self):
            del self.__logFileName


        def getBaseFolder(self):
            return self.__baseFolder

        def createFolder(self):
            return self.__createFolder

        def updateReg(self):
            return self.__updateReg

        def setBaseFolder(self, value):
            self.__baseFolder = path.normcase(path.normpath(value))

        def setCreateFolder(self, value):
            self.__createFolder = value

        def setUpdateReg(self, value):
            self.__updateReg = value

        def delBaseFolder(self):
            del self.__baseFolder

        def delCreateFolder(self):
            del self.__createFolder

        def delUpdateReg(self):
            del self.__updateReg
        
        def autoSave(self):
            return self.__autoSave
        
        def setAutoSave(self, value):
            self.__autoSave=value
        
        def delAutoSave(self):
            del self.__autoSave
        
        _baseFolder = property(getBaseFolder, setBaseFolder, delBaseFolder, "Path to the folder where to save the log file")
        _createFolder = property(createFolder, setCreateFolder, delCreateFolder, "Should the folder be created if it doesn't exist?")
        _updateReg = property(updateReg, setUpdateReg, delUpdateReg, "should the Spike2 section of the registry updated?")
        _autoSave = property(autoSave, setAutoSave, delAutoSave, "shoud the log file be automatically saved?")
        _logFileName = property(getLogFileName, setLogFileName, delLogFileName, "file name to write to in auto save mode")

class pCO2MonitorThread(threading.Thread):
    def __init__(self,*args,**kargs):
#        print "%s - entering pCO2MonitorThread.__init__()\n"%time.strftime("%H:%M:%S") #DEBUG
#        print "initializing serial communication..." #DEBUG
        self.__serial = serial.Serial(*args,**kargs)
#        print "...OK\n" #DEBUG
#        print "initializing Thread object..." #DEBUG
        self.__PCO2Deck = deque()
        self.__BreathRateDeck = deque()
        self.__inputRegexp = re.compile("([0-9]{1}\.[0-9]{1,2}),([0-9]{1,3})\r")
        self.__keepRunning = True
        threading.Thread.__init__(self)
        print "...OK\n" #DEBUG

    def run(self):
#        print "%s - Entering Thread loop\n"%time.strftime("%H:%M:S") #DEBUG
        while self.__keepRunning:
#            print "%s - Reading from serial line..."%time.strftime("%H:%M:%S") #DEBUG
            myBuffer = self.__serial.readline(None,'\r')
#            print "...Done [%s]\n"%time.strftime("%H:%M%S") #DEBUG
            if len(myBuffer)>0:
#                print "Buffer: <%s>\n"%myBuffer #DEBUG
                matchIterator = self.__inputRegexp.finditer(myBuffer)
                for match in matchIterator:
#                    print "Found match <%s>\n"%match #DEBUG
                    self.__PCO2Deck.append(float(match.group(1)))
                    self.__BreathRateDeck.append(float(match.group(2)))
            while len(self.__PCO2Deck)>PCO2_ITEM_DECK_MAX_LEN:
                self.__PCO2Deck.popleft()
                self.__BreathRateDeck.popleft()
#            print "Length of the PCO2Deck is now %d\n"%len(self.__PCO2Deck) #DEBUG
#            print "Length of the BreathMonitorDeck is now %d\n"%len(self.__BreathRateDeck) #DEBUG
#        print "%s - Exiting Thread loop\n"%time.strftime("%H:%M:%S") #DEBUG

    def getMeanValues(self):
#        print "%s - In pCO2MonitorThread.getMeanValues()\n"%time.strftime("%H:%M:%S") #DEBUG
        nPCO2Deck = float(len(self.__PCO2Deck))
        sumPCO2Deck = float(sum(self.__PCO2Deck))
        nBRDeck = float(len(self.__BreathRateDeck))
        sumBRDeck = float(sum(self.__BreathRateDeck))
        
        print "PCO2Deck - N=%d\n"%nPCO2Deck

        if nPCO2Deck > 0 and nBRDeck > 0:
            retVal = ( sumPCO2Deck/nPCO2Deck , sumBRDeck/nBRDeck  )
        else:
            retVal = (0,0)
        return retVal
    
    def stop(self):
        print "%s - Stop requested\n"%time.strftime("%H:%M:%S")
        self.__keepRunning = False

if __name__ == "__main__":
    pass
    