#!/usr/bin/python
# -*- coding: utf-8 -*-
from model import jsonArray
import threading
from Queue import Queue
import time
import matplotlib
import numpy as np
import cStringIO
from PIL import Image
import logging
import redis
import datetime
from PyQt4 import QtCore
from PyQt4.QtCore import QThread
import random
from model import thread

from model import getNeonData

class setHeartbeat(threading.Thread):

    def __init__(
        self,
        neonRedis,
        refreshtime,
        neonpath,
        status,
        ):
        #super(setHeartbeat, self).__init__()
        #QThread.__init__(self)
        threading.Thread.__init__(self)
        self.paused = False
        self.pause_cond = threading.Condition(threading.Lock())
        self.thread_stop = False

        self.neonRedis=neonRedis
        self.refreshtime=refreshtime
        self.neonpath=neonpath
        self.status=status

	self.mylist=["configure", "start", "stop", "pause", "abort"]
    def process(self):
        try:
            _data={'time':time.strftime('%Y-%m-%d %H:%M:%S.%03d'),'status':self.status}
            self.neonRedis.set(self.neonpath, _data)

	    i=random.randint(0,5)
	    self.neonRedis.set("/GPPD/command/pilot", self.mylist[i])
            #logging.info(str(_data))
            #self.logGui.logWrite(str(_data))
        except:
            #self.logGui.logWrite("WARNING", "Heartbeat Send failed")
            pass

    def run(self):
        while True:
            self.process()
            time.sleep(self.refreshtime)

class dataThread(QtCore.QObject):
    def __init__(self, parent,  gui, neonServer=None, progressPath=None, protonPath=None, neutronPath=None, pulsePath=None, refreshTime=1.0):
        super(self.__class__, self).__init__()
        self.gui=gui
        self.worker = getNeonData.getNeonData(self, neonServer, progressPath, protonPath, neutronPath, pulsePath, refreshTime)
        self.worker_thread = getNeonData.workerThread(gui)
        self.worker.moveToThread(self.worker_thread)
        self.worker_thread.started.connect(self.worker.process)
        self.worker_thread.start()
        self.worker.finished.connect(self.worker_thread.quit)
        
        self.worker.signalLog.connect(self.gui.setLog)
        self.worker.signalProgress.connect(self.gui.setProgressData) 
        self.worker.signalStatus.connect(self.gui.setCanvasData) 
        self.worker.signalMonitor.connect(self.gui.setMonitorCanvas)
        self.worker.signalExperiment.connect(self.gui.setUserData)
        
    def pause(self):
        if self.worker_thread.isRunning():
            #self.worker_thread.terminate()
            #self.worker_thread.wait()
            self.worker.set(False)

    def resume(self):
        if not self.worker_thread.isRunning():
            self.worker.set(True)
            self.worker_thread.start()

    def clear(self):
        if self.worker_thread.isRunning():
            self.worker_thread.terminate()
            self.worker_thread.wait()

            self.signalStatus.emit('')
            self.worker_thread.start()

    def start(self):
        self.worker_thread.start()

    def stop(self):
        if self.worker_thread.isRunning():
            self.worker_thread.terminate()

    def setImgPath(self, value):
        self.worker.setImgPath(value)

    def setDataPath(self, kwargs):
        self.worker.setDataPath(kwargs)

    def getTabIndex(self):
        return self.worker.getTabIndex()

    def getMonitorTOF(self):
        return self.worker.getMonitorTOF()

    def getDetectorIndex(self):
        return self.gui.getDetectorIndex()

class getCommand(QtCore.QObject):
    def __init__(self, parent,  gui, neonServer=None, neonPath=None, refreshTime=None):
        super(self.__class__, self).__init__()

        self.gui=gui
        self.value = ''
        self.worker = thread.workerObject(neonServer, neonPath, refreshTime)
        self.worker_thread = thread.workerThread(gui)
        self.worker.moveToThread(self.worker_thread)       
        self.worker_thread.started.connect(self.worker.process)
        self.worker_thread.start()
        
        self.worker.finished.connect(self.worker_thread.quit)
        self.gui.getCommandButton().clicked.connect(self.pause)
        self.gui.getCommandButton().clicked.connect(self.resume)
 
        self.worker.signalStatus.connect(self.gui.setCommand)
        #parent.aboutToQuit.connect(self.stop)

    def pause(self):
        if self.worker_thread.isRunning():
            #self.worker_thread.terminate()
            #self.worker_thread.wait()
            self.worker.set(False)

    def resume(self):
        if not self.worker_thread.isRunning():
            self.worker.set(True)
            self.worker_thread.start()

    def clear(self):
        if self.worker_thread.isRunning():
            self.worker_thread.terminate()
            self.worker_thread.wait()

            self.signalStatus.emit('')
            self.worker_thread.start()

    def start(self):
        self.worker_thread.start()

    def stop(self):
        if self.worker_thread.isRunning():
            self.worker_thread.terminate()

class connectNeon():
    
    def __init__(
        self,
        ip,
        port,
        timeout,
        ):

        self.status=False
        client=False
        self.server=None
        begin=time.time()
        while True:
            if not self.server:
                self.server = redis.Redis(host=ip, port=port, db=0, socket_connect_timeout=1)
            else:
                try:
                    client=self.server.client_list()
                except (redis.exceptions.ConnectionError):
                    logging.warning("Attempt to connect NEON again!")
                if client:
                    self.status = True
                    logging.info("NEON connected")
                    break
                else:
                    #logging.exception("NEON not available")
                    logging.error("NEON not available")
                if time.time()-begin>timeout:
                    logging.info("NEON connect timeout")
                    break

    def getStatus(self):
        return self.status

    def getServer(self):
        return self.server
      
'''  
class dataSet(threading.Thread):

    def __init__(
        self,
        threadID,
        neonRedis,
        refreshtime,
        neonpathXaxis,
        neonpathYaxis,
        neonpathZarray,
        neonpathCvalue,
        arrayZ,
        valueC,
        ):

        threading.Thread.__init__(self)
        self.paused = False
        self.pause_cond = threading.Condition(threading.Lock())
        self.thread_stop = False

        self.neonRedis = neonRedis
        self.neonpathX = neonpathX
        self.neonpathY = neonpathY
        self.neonpathZ = neonpathZ
        self.neonpathC = neonpathC

        self.arrayZ = arrayZ
        self.valueC = valueC

        self.refreshtime = refreshtime

    def setXaxis(self, xbins):
        _json_data = jsonArray.jsonEncoder(xbins)
        self.neonRedis.set(self.neonpathXaxis, _json_data)

    def setYaxis(self, ybins):
        _json_data = jsonArray.jsonEncoder(ybins)
        self.neonRedis.set(self.neonpathYaxis, _json_data)

    def process(self):
        be = time.time()

        if self.neonpathCvalue != None:
            _dataC = self.valueC.get()
            self.neonRedis.set(self.neonpathCvalue, _dataC)

        _jsonZ = self.arrayZ.get()
        _jsonZ = jsonArray.jsonEncoder()
        self.neonRedis.set(self.neonpathZarray, _jsonZ)

        print time.time() - be

    def run(self):
        while True:
            self.process()
            time.sleep(self.refreshtime)

    def destroy(self):
        self.neonRedis.delete(self.neonX)
        self.neonRedis.delete(self.neonY)
        self.neonRedis.delete(self.neonZ)
        self.neonRedis.delete(self.neonC)

    def pause(self):
        self.paused = True
        self.pause_cond.acquire()

    def resume(self):
        self.paused = False
        self.pause_cond.notify()
        self.pause_cond.release()

    def stop(self):
        self.thread_stop = True


class dataGet(threading.Thread):

    def __init__(
        self,
        threadID,
        neonRedis,
        refreshtime,
        neonpathXaxis,
        neonpathYaxis,
        neonpathZarray,
        neonpathCvalue,
        button,
        canvas,
        ):

        threading.Thread.__init__(self)
        self.paused = False
        self.pause_cond = threading.Condition(threading.Lock())
        self.thread_stop = False

        self.neonRedis = neonRedis
        self.neonpathXaxis = neonpathXaxis
        self.neonpathYaxis = neonpathYaxis
        self.neonpathZarray = neonpathZarray
        self.neonpathCvalue = neonpathCvalue

        self.button = button
        self.canvas = canvas
        self.ax = canvas.ax

        self.getAxis()

    # self.arrayZ=arrayZ
        # self.valueC=valueC

        self.refreshtime = refreshtime

    def getAxis(self):
        _json_data = self.neonRedis.get(self.neonpathXaxis)
        #print _json_data
        _x = jsonArray.jsonDecoder(_json_data)

        _json_data = self.neonRedis.get(self.neonpathYaxis)
        _y = jsonArray.jsonDecoder(_json_data)

        _nx = len(_x)
        _ny = len(_y)

        self.xbin = np.zeros((_nx, _ny))
        self.ybin = np.zeros((_nx, _ny))

        for i in range(_nx):
            for j in range(_ny):
                self.xbin[i][j] = _x[i]
                self.ybin[i][j] = _y[j]

    def initXYaxis(self):
        pass

    # self.ax.set_xdata(self.getXaxis())....
    # self.ax.set_ydata(self.getYaxis())....
    # self.axis = self.ax.plot(self.getXaxis(), self.getYaxis(), "cool")....

    def process(self):
        be = time.time()

        if self.neonpathCvalue != None:
            _dataC = self.neonRedis.get(self.neonpathCvalue)
            print _dataC

            self.button.setText(str(_dataC))

        if self.neonpathZarray != None:
            _jsonZ = self.neonRedis.get(self.neonpathZarray)

            # _dataZ=jsonArray.jsonDecoder(_jsonZ)

            _imdata = cStringIO.StringIO(_jsonZ)
            _im = Image.open(_imdata)  # .getvalue())
            self.canvas.ax.imshow(_im)

        print time.time() - be

    # self.ax.pcolormesh(self.xbin, self.ybin, _dataZ)
    # self.canvas.draw()....

        # _jsonZ=self.neonRedis.get(self.neonpathZarray)
            # self.arrayZ.put(jsonArray.jsonDecoder(_jsonZ))
            # self.arrayZ.task_done()

    def run(self):
        while True:
            self.process()
            time.sleep(self.refreshtime)

    def pause(self):

        # self.paused = True
        # self.pause_cond.acquire()

        self.can_run.set()
        with self.arrayZ.mutex:
            self.arrayZ.queue.clear()
            self.valueC.queue.clear()

    def resume(self):

        # self.paused = False
        # self.pause_cond.notify()
        # self.pause_cond.release()

        self.can_run.clear()

    def stop(self):
        self.paused = True
        self.pause_cond.acquire()
        self.can_run.set()

'''
