#!/usr/bin/python

import wx
from wx import xrc
import serial #@UnresolvedImport
import comedi #@UnresolvedImport
from SurgicalLogClasses import mouseClass, expClass, drugClass,\
    surgicalLogConfigClass, pCO2MonitorThread #@UnusedImport
from SurgicalLogGui import mainFrameClass
from PhysioMonitor.AladdinPump import AladdinPump
import sys
import os



SurgicalLogInfo = wx.AboutDialogInfo()
SurgicalLogInfo.SetName("SurgicalLog")
SurgicalLogInfo.AddDeveloper("Marin Manuel")
SurgicalLogInfo.SetCopyright("This software is released under the terms of the GPL")
SurgicalLogInfo.SetDescription("SurgicalLog helps keep track of drug injections and physiological data during an experiment")
SurgicalLogInfo.SetLicence("see LICENCE.txt")

recordPath='/Users/manuel/src/SurgicalLog/'

#Global constants for the serial port to the PCO2Monitor. Adjust as needed
CO2MONITOR_SERIAL_PORT     = 3 #COM4
CO2MONITOR_SERIAL_BAUD_RATE = 2400
CO2MONITOR_SERIAL_PARITY   = serial.PARITY_NONE
CO2MONITOR_SERIAL_STOPBITS = serial.STOPBITS_ONE
CO2MONITOR_SERIAL_BYTESIZE = serial.EIGHTBITS
CO2MONITOR_SERIAL_TIMEOUT  = None

#Global constants for the serial port on the Syringe Pump
SYRINGEPUMP_SERIAL_PORT = 0

#data acq configuration
comediConfig = dict()
comediConfig['device'] = '/dev/comedi0'
comediConfig['subDevice'] = 0
comediConfig['nbChans'] = 5
comediConfig['channels'] = [0,1,2,3,4]
comediConfig['gains'] = [0,0,0,0,0]
comediConfig['refs'] = [comedi.AREF_GROUND,comedi.AREF_GROUND,comedi.AREF_GROUND,comedi.AREF_GROUND,comedi.AREF_GROUND]
comediConfig['sampleFreq'] = 1000




if __name__ == '__main__':
    dn = os.path.dirname(os.path.realpath(sys.argv[0]))
    res = xrc.XmlResource(os.path.join(dn,"SurgicalLog.xrc"))
    xrc.XmlResource.Set(res)
    
    #start with a "fresh" mouse
    theMouse = mouseClass()
    theExp = expClass(mouse=theMouse)
    theExp.date = wx.DateTime.Now()

    #get the list of previous dugs to save time
    drugList = []
    config = wx.Config(SurgicalLogInfo.GetName())
    if config.HasGroup("drugs"):
        config.SetPath("/drugs")
        numDrugs = config.GetNumberOfEntries()/2
        for i in range(0,numDrugs):
            drugName = config.Read("%d_name"%i,"default name")
            drugDose = config.ReadInt("%d_name_dose"%i,0)
            drugList.append(drugClass(drugName,drugDose))
    theExp.drugList = drugList

    #get list of mouse types
    mouseTypes = []
    config.SetPath("/")
    if config.HasGroup("mouseTypes"):
        config.SetPath("/mouseTypes")
        for i in range(0,config.GetNumberOfEntries()):
            mouseTypes.append(config.Read("%d"%i,""))
    theExp.mouseTypes = mouseTypes
    
    #options
    config.SetPath("/")
    surgicalLogConfig = surgicalLogConfigClass()
    if config.Exists("baseFolder"):
        surgicalLogConfig.setBaseFolder(config.Read("baseFolder"));
    if config.Exists("createFolder") and config.GetEntryType("createFolder")==wx.Config.Type_Boolean:
        surgicalLogConfig.setCreateFolder(bool(config.ReadBool("createFolder")))
    if config.Exists("updateReg") and config.GetEntryType("updateReg")==wx.Config.Type_Boolean:
        surgicalLogConfig.setUpdateReg(bool(config.ReadBool("updateReg")))
    if config.Exists("autoSave") and config.GetEntryType("autoSave")==wx.Config.Type_Boolean:
        surgicalLogConfig.setUpdateReg(bool(config.ReadBool("autoSave")))
    
    app = wx.App(redirect=False)

    #initialize the CO2 Monitor configuration
#    try:
#        print "creating pCO2Monitor" #DEBUG
#        pCO2Monitor = pCO2MonitorThread(port=CO2MONITOR_SERIAL_PORT, baudrate=CO2MONITOR_SERIAL_BAUD_RATE, bytesize=CO2MONITOR_SERIAL_BYTESIZE, parity=CO2MONITOR_SERIAL_PARITY, stopbits=CO2MONITOR_SERIAL_STOPBITS, timeout=CO2MONITOR_SERIAL_TIMEOUT)
#    except Exception as inst:
#        print type(inst)     # DEBUG - the exception instance
#        print inst.args      # DEBUG - arguments stored in .args
#        print inst           # DEBUG - __str__ allows args to printed directly
#        pCO2Monitor = None
#        errorDlg = wx.MessageDialog(None, "Error while initializing communication with CO2 Monitor",style=wx.OK|wx.ICON_ERROR)
#        errorDlg.ShowModal()
#        errorDlg.Destroy()
    pCO2Monitor = None

    #initialize the syringe pump
    pumpValid = False
    while (not pumpValid):
        try:
            syringePump = AladdinPump(SYRINGEPUMP_SERIAL_PORT,19200,0)
            # @type syringePump syringePumpClass
            syringePump.doBeep(1)
            pumpValid=True
        except Exception as inst:
            print inst
            syringePump = None
            errorDlg = wx.MessageDialog(None, 
                "Cannot communicate with syringe pump. Maybe it is off?\nRetry?",
                style=wx.YES|wx.NO|wx.CANCEL|wx.ICON_QUESTION)
            try:
                ret = errorDlg.ShowModal()
                if ret == wx.ID_YES:
                    pumpValid = False
                    syringePump = None
                elif ret == wx.ID_NO:
                    pumpValid = True
                    syringePump = None
                else:
                    sys.exit(1)
            finally:
                errorDlg.Destroy()
    
    mainFrame = mainFrameClass(exp=theExp, info=SurgicalLogInfo, config=surgicalLogConfig, pCO2Monitor=pCO2Monitor, syringePump=syringePump, aiConfig=comediConfig)
    mainFrame.Show()
    app.MainLoop()
    
    #save the list of drugs
    config.SetPath("/")
    config.DeleteGroup("drugs")
    config.SetPath("/drugs")
    index=0
    for drug in theExp.drugList:
        config.Write("%d_name"%index,drug.name)
        config.WriteInt("%d_name_dose"%index,drug.dose)
        index+=1
    config.Flush()

    #save list of mouse types
    config.SetPath("/")
    config.DeleteGroup("mouseTypes")
    config.SetPath("/mouseTypes")
    index=0
    for mouseType in theExp.mouseTypes:
        config.Write("%d"%index,mouseType)
        index+=1
    config.Flush()
    
    #save config
    config.SetPath("/");
    config.Write("baseFolder", surgicalLogConfig.getBaseFolder())
    config.WriteBool("createFolder", surgicalLogConfig.createFolder())
    config.WriteBool("updateReg", surgicalLogConfig.updateReg())
    config.WriteBool("autoSave", surgicalLogConfig.autoSave())
    config.Flush()
        
