#!/usr/bin/python

import wx
from wx import xrc
import serial  # @UnresolvedImport
import comedi  # @UnresolvedImport
# noinspection PyUnresolvedReferences
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/manip/records/'

# 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'] = [4, 3, 8, 19, 2]
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'] = 10.

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
    syringePump = None
    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()
