'''
Created on Jun 12, 2012

@author: manuel
'''
import serial
import threading
import os
import struct

import numpy as np

from Utils import deinterleaveData, UpdateCanvasEvent
import wx
import time
import comedi #@UnresolvedImport

DEBUG=False
SLEEP_TIME=0.75

class ComediThread(threading.Thread):
    def __init__(self, frame, fd, nbChans, bufferSize=10000):
        if DEBUG: print "in readerThread __init__"
        threading.Thread.__init__(self)
        self.frame = frame
        self.fd = fd
        self.nbChans = nbChans
        self.bufferSize = bufferSize
        self.reading = False
        
    def run(self):
        if DEBUG: print "Reader thread running..."
        self.reading = True
        data = []
        n = 0
        lastPostedEvent = time.time()
        while (self.reading):
            try:
                if DEBUG: print "reading..."
                line = os.read(self.fd,self.bufferSize)
                n = len(line)/2 # 2 bytes per 'H'
                if DEBUG: print "read %s(...) (%d bytes). data is %d items"%(line[:5],len(line),len(data))
                unpack = struct.unpack('%dH'%n,line)
                if DEBUG: print "unpacking... got %d values"%len(unpack)
                data.extend(unpack)
                if DEBUG: print "appending to data. data is now (%d items) %s"%(len(data),str(data))
                if DEBUG: print "de-interleaving..."
                out,data = deinterleaveData(data,self.nbChans)
                if DEBUG: print "returned a (%d,%d) array and kept %d for next round"%(out.shape[0],out.shape[1],len(data))
                self.frame.processNewData(out)
                if time.time()-lastPostedEvent>SLEEP_TIME:
                    evt = UpdateCanvasEvent()
                    wx.PostEvent(self.frame, evt)
                    lastPostedEvent=time.time()
            except IOError:
                raise Exception("Fatal Error: %s" % (comedi.comedi_strerror(comedi.comedi_errno())))


class SerialThread(threading.Thread):
    def __init__(self, frame, indices):
        if DEBUG: print "in SerialThread __init__"
        threading.Thread.__init__(self)
        self.frame = frame
        self.indices = indices
        self.reading = False
        self.somno = serial.Serial(port="/dev/SomnoSuite", baudrate=115200, bytesize=8, parity='N', stopbits=1,
                                   rtscts=True, dsrdtr=True)
        self.physio = serial.Serial(port="/dev/PhysioSuite", baudrate=115200, bytesize=8, parity='N', stopbits=1,
                                    rtscts=True, dsrdtr=True)

    def run(self):
        if DEBUG: print "serial thread running..."
        self.reading = True
        lastPostedEvent = time.time()
        while (self.reading):
            try:
                a = self.readSer()
                d = a[self.indices]
                if DEBUG: print "sending data for processing:", d
                self.frame.processNewData(d)
                if time.time()-lastPostedEvent>SLEEP_TIME:
                    evt = UpdateCanvasEvent()
                    wx.PostEvent(self.frame, evt)
                    lastPostedEvent=time.time()
            except:
                if DEBUG: print "Exception while reading data, skipping..."
                pass

    def readSer(self):
        bufferSize = [800, 905]
        nbParams = 21
        a = self.physio.readlines(bufferSize[0])
        b = self.somno.readlines(bufferSize[1])
        comb = [c + d for c, d in zip(a, b)]  # combine both arrays
        comb = [c.replace('*', 'NaN').split() for c in comb]  # replace + and split into individual values
        comb = [c for c in comb if len(c) == nbParams]  # drop lines with incorrect number of values
        c = np.array(comb, dtype=np.float64)
        return c.T
