#!/usr/bin/python

# Howto, Code license, Credits, etc: http://code.google.com/B/BCI-Project-Triathlon/

noGL = False   # Set noGL to True for disabling the use of OpenGL (to gain speed, or to avoid python-wx-opengl problems)

import numpy
import wx
import math
import threading
import random
import sys
import os
import random

import InputManager
import WXElements

try:
    from wx import glcanvas
    haveGLCanvas = True
except ImportError:
    haveGLCanvas = False
    noGL = True
    print "Will start without OpenGL, because wx.glcanvas is not available."

try:
    from OpenGL.GL import *
    from OpenGL.GLU import *
    from OpenGL.GLUT import *
    haveOpenGL = True
except ImportError:
    haveOpenGL = False
    noGL = True
    print "Will start without OpenGL, because PyOpenGL is not available."

class AppSettings():
    def __init__(self,
                 niaFPS           = 10,
                 deviceName       = "OCZ Neural Impulse Actuator",
                 bands            = [(2,4),(5,7),(8,10),(11,13),(14,16),(17,20),(21,24),(25,30),(31,45)]):
        self.niaFPS          = niaFPS
        self.deviceName      = deviceName
        self.bands           = bands

class RawVisualizationPanel(WXElements.GLCanvasBase):
   def InitGL(self):
       light_diffuse = [1.0, 1.0, 1.0, 1.0]
       light_position = [1.0, 1.0, 1.0, 0.0]
       glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
       glLightfv(GL_LIGHT0, GL_POSITION, light_position)
       glEnable(GL_LIGHTING)
       glEnable(GL_LIGHT0)
       glEnable(GL_DEPTH_TEST)
       glClearColor(0.0, 0.0, 0.0, 1.0)
       glClearDepth(1.0)
       glMatrixMode(GL_PROJECTION)
       glLoadIdentity()
       gluPerspective(40.0, 1.0, 1.0, 30.0)
       glMatrixMode(GL_MODELVIEW)
       glLoadIdentity()
       gluLookAt(0.0, 0.0, 10.0,
                 0.0, 0.0, 0.0,
                 0.0, 1.0, 0.0)
   def OnDraw(self):
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
       glLoadIdentity()
       glEnableClientState(GL_VERTEX_ARRAY)
       for eachI in range(len(bciDevice.devices)):
           glColor(0.55,0.55,0.3)
           wave_array = []
           for historyIndex in reversed(xrange(500)):
               wave_array =  wave_array +[[-1.0+ (2.0*float(historyIndex)/499.0), -1.0+((2.0*eachI)+(0.0000001*bciDevice.working_Data(eachI)[-1-historyIndex]))/len(bciDevice.devices)]]
           glVertexPointerf(wave_array)
           glDrawArrays(GL_LINE_STRIP, 0, len(wave_array))
       for eachI in range(len(bciDevice.devices)):
           glColor(0.55,0.55,0.3)
           glRasterPos2f(0.2 ,-0.5 +( (2.0*eachI))/len(bciDevice.devices))
           for eachChar in ("Device "+str(eachI)+" Raw"):
                  glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, ord(eachChar))
       self.SwapBuffers()
   def newReading(self):
       if self.GetGrandParent().GetSelection()==0:
           self.SetCurrent()
           self.OnDraw()
   def resetReading(self):
       if self.GetGrandParent().GetSelection()==0:
           self.SetCurrent()
           self.OnDraw()

class FFTVisualizationPanel(WXElements.GLCanvasBase):
   def InitGL(self):
       light_diffuse = [1.0, 1.0, 1.0, 1.0]
       light_position = [1.0, 1.0, 1.0, 0.0]
       glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
       glLightfv(GL_LIGHT0, GL_POSITION, light_position)
       glEnable(GL_LIGHTING)
       glEnable(GL_LIGHT0)
       glEnable(GL_DEPTH_TEST)
       glClearColor(0.0, 0.0, 0.0, 1.0)
       glClearDepth(1.0)
       glMatrixMode(GL_PROJECTION)
       glLoadIdentity()
       gluPerspective(40.0, 1.0, 1.0, 30.0)
       glMatrixMode(GL_MODELVIEW)
       glLoadIdentity()
       gluLookAt(0.0, 0.0, 10.0,
                 0.0, 0.0, 0.0,
                 0.0, 1.0, 0.0)
   def OnDraw(self):
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
       glLoadIdentity()
       glEnableClientState(GL_VERTEX_ARRAY)
       for eachI in range(len(bciDevice.devices)):
           for eachFingerI in range(len(settings.bands)):
               everyFingerI = (eachI*len(settings.bands)) + eachFingerI
               glColor(everyFingerI*0.05+0.3,-everyFingerI*0.05+0.9,float(everyFingerI%2))
               seg = bciDevice.frequencies(eachI,settings.bands[eachFingerI][0],settings.bands[eachFingerI][1])
               avg = sum(seg)/len(seg)
               wave_array = [[ -1.0+ (2.0*float(settings.bands[eachFingerI][0])/49.0) , -1.0+((2.0*eachI))/len(bciDevice.devices) ],
                             [ -1.0+ (2.0*float(settings.bands[eachFingerI][0])/49.0) , -1.0+((2.0*eachI) + avg)/len(bciDevice.devices)],
                             [ -1.0+ (2.0*float(settings.bands[eachFingerI][1])/49.0), -1.0+((2.0*eachI))/len(bciDevice.devices)],
                             [ -1.0+ (2.0*float(settings.bands[eachFingerI][1])/49.0), -1.0+((2.0*eachI) + avg)/len(bciDevice.devices)]]
               glVertexPointerf(wave_array)
               glDrawArrays(GL_QUAD_STRIP, 0, len(wave_array))
       for eachI in range(len(bciDevice.devices)):
           glColor(1.0,0.55,0.3)
           wave_array = []
           for freqs in reversed(xrange(50)):
               wave_array =  wave_array +[[-1.0+ (2.0*float(freqs)/49.0),  -1.0+((2.0*eachI)+(bciDevice.frequencies(eachI,0,50)[freqs]))/len(bciDevice.devices)]]
           glVertexPointerf(wave_array)
           glDrawArrays(GL_LINE_STRIP, 0, len(wave_array))
       for eachI in range(len(bciDevice.devices)):
           glColor(1.0,0.55,0.3)
           glRasterPos2f(0.2 ,-0.55 +( (2.0*eachI))/len(bciDevice.devices))
           for eachChar in ("Device "+str(eachI)+" FFT"):
                  glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, ord(eachChar))
           glColor(0.55,0.55,0.55)
           glRasterPos2f(0.2 ,-0.60 +( (2.0*eachI))/len(bciDevice.devices))
           for eachChar in ("Device "+str(eachI)+" EEG Bands"):
                  glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, ord(eachChar))
       self.SwapBuffers()
   def newReading(self):
       if self.GetGrandParent().GetSelection()==2:
           self.SetCurrent()
           self.OnDraw()
   def resetReading(self):
       if self.GetGrandParent().GetSelection()==2:
           self.SetCurrent()
           self.OnDraw()

class FFTHistoryVisualizationPanel(WXElements.GLCanvasBase):
   def __init__(self, parent):
       self.ylists = [[ 0.0 for each in xrange(len(settings.bands)*len(bciDevice.devices))] for every in range(100)]
       self.xlist = [float(i)/float(-1+len(self.ylists[0])) for i in xrange(len(self.ylists[0]))]
       WXElements.GLCanvasBase.__init__(self, parent)
   def InitGL(self):
       light_diffuse = [1.0, 1.0, 1.0, 1.0]
       light_position = [1.0, 1.0, 1.0, 0.0]
       glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
       glLightfv(GL_LIGHT0, GL_POSITION, light_position)
       glEnable(GL_LIGHTING)
       glEnable(GL_LIGHT0)
       glEnable(GL_DEPTH_TEST)