from mantid.simpleapi import *
import jsonArray
import time
import datetime
import json
import multiprocessing
from multiprocessing import Process, Manager
import shutil
import path

class monitorIO(multiprocessing.Process):
    def __init__(self, neonRedis, refreshtime, monitorList, myDict, logger):
        super(monitorIO, self).__init__()

        self.refreshtime=refreshtime
        self.neonRedis_write=neonRedis
        self.neonRedis_read=neonRedis
        self.monitorList=monitorList
        self.logger=logger
        self.myDict=myDict
        self.confJudge=True
        self.neonpathValue=[]
        self.neonpathPid=[]
        self.neonpathTof=[]
        for name in self.monitorList:
            self.neonpathValue.append("/GPPD/workspace/"+name+"/value")
            self.neonpathPid.append("/GPPD/workspace/"+name+"/pid")
            self.neonpathTof.append("/GPPD/workspace/"+name+"/tof")

    def get1Ddata(self, path):
        data=[]
        _json=self.neonRedis_read.get(path)
        while _json is None:
            self.logger.warning("no 1D data in "+path+str(datetime.datetime.now()))
            _json=self.neonRedis_read.get(path)
            time.sleep(20)
        data=jsonArray.jsonDecoder(_json)
        return data

    def getDataFromNeon(self, monitor, path):
        self.monValue=[]
        _json=self.neonRedis_read.get(path)
        while _json is None:
            self.logger.warning("no 2D data in "+path+" "+str(datetime.datetime.now()))
            _json=self.neonRedis_read.get(path)
            time.sleep(10)
        _array=jsonArray.jsonDecoder(_json)
        a=0
        for ix in _array:
            a=a+sum(ix)
            for iy in ix:
                self.monValue.append(iy)
        self.neonRedis_write.set("/GPPD/workspace/MantidData/"+monitor+"/neutroncounts", json.dumps(a))

    def createWorkspace(self, monitor):
        LoadCSNSRaw(OutputWorkspace=monitor, PixelID_bank=[0,1], TimeOfFlight_bank=[0,8], Counts_bank=[1,1], PixelID_monitor=self.monPid, TimeOfFlight_monitor=self.monTof, Counts_monitor=self.monValue)
        #SaveNexus(InputWorkspace=monitor+'_2', Filename='./'+monitor+'.nxs')
        #time.sleep(60)
        LoadInstrument(Workspace=monitor+"_2", Filename='./instrument/'+monitor+'.xml', RewriteSpectraMap='True')
        ConvertUnits(InputWorkspace=monitor+'_2', OutputWorkspace=monitor+'_wave', Target='Wavelength', AlignBins = True)
        SumSpectra(InputWorkspace=monitor+'_wave', OutputWorkspace=monitor+"_wave", IncludeMonitors=True)
        SaveNexus(InputWorkspace=monitor+'_wave', Filename='./'+monitor+'.nxs')
        #Rebin(InputWorkspace=monitor+"_wave",OutputWorkspace=monitor+"_wave", Params='0.001,0.005,8')
        ConvertUnits(InputWorkspace=monitor+'_wave', OutputWorkspace=monitor+'_tofCounts', Target='TOF', AlignBins = True)

    def set1DdataToNeon(self,wsname, path1, path2):
        name=mtd[wsname]
        x=[]
        v=[]
        v=name.readY(0)
        _tmp=name.readX(0)
        for j in range(len(_tmp)-1):
            x.append(_tmp[j]+(_tmp[j+1]-_tmp[j])/2)
        self.neonRedis_write.set(path1, jsonArray.jsonEncoder(x))
        self.neonRedis_write.set(path2, jsonArray.jsonEncoder(v))

    def setXYdata(self,monitor):
        xaxis=[]
        yaxis=[]
        counts=[]
        name=mtd[monitor+"_2"]
        for j in range(name.getNumberHistograms()):
            det=name.getDetector(j)
            pos=det.getRelativePos()
            xaxis.append(pos.X())
            yaxis.append(pos.Y())
            counts.append(sum(name.readY(j)))
        xaxis=list(set(xaxis))
        yaxis=list(set(yaxis))
        xaxis.sort()
        yaxis.sort()
        for i in range(len(yaxis)):
            yaxis[i]=yaxis[i]*1000
        for i in range(len(xaxis)):
            xaxis[i]=xaxis[i]*1000

        vaxis=[[] for m in range(len(yaxis))]
        n=0
        for j in range(len(yaxis)):
            for k in range(len(xaxis)):
                vaxis[j].append(counts[n])
                n=n+1
        self.neonRedis_write.set("/GPPD/workspace/MantidData/"+monitor+"/xy_image/x",jsonArray.jsonEncoder(xaxis))
        self.neonRedis_write.set("/GPPD/workspace/MantidData/"+monitor+"/xy_image/y",jsonArray.jsonEncoder(yaxis))
        self.neonRedis_write.set("/GPPD/workspace/MantidData/"+monitor+"/xy_image/value",jsonArray.jsonEncoder(vaxis))
        #print (vaxis)
        self.logger.debug("set xy data for "+monitor+" "+str(datetime.datetime.now()))

    def dataSet(self, monitor):
        # set tof counts
        self.set1DdataToNeon(monitor+"_tofCounts","/GPPD/workspace/MantidData/"+monitor+"/tof","/GPPD/workspace/MantidData/"+monitor+"/counts")
        # set wave counts
        self.set1DdataToNeon(monitor+"_wave","/GPPD/workspace/MantidData/"+monitor+"/wave","/GPPD/workspace/MantidData/"+monitor+"/intensity")
        # set XY data
        self.setXYdata(monitor)
        DeleteWorkspace(Workspace=monitor)
        DeleteWorkspace(Workspace=monitor+'_tofCounts')
        DeleteWorkspace(Workspace=monitor+'_wave')

    def process(self):
        if self.myDict['configure']:
            if self.confJudge:
                self.monTof=[]
                self.monPid=[]
                self.monPid=self.get1Ddata(self.neonpathPid[0])
                self.monTof=self.get1Ddata(self.neonpathTof[0])
                #path.clearRedis(self.neonRedis_write)
                self.logger.debug("finish new configuring")
                self.confJudge=False
            else:
                pass
        else:
            self.confJudge=True

        if self.myDict['running']:
            self.logger.debug("start running program")        
            for i in range(len(self.monitorList)):
                #try:
                self.getDataFromNeon(self.monitorList[i], self.neonpathValue[i])
                #except:
                #    self.myDict['error']=True
                #    self.myDict['running']=False
                #    self.logger.error("error in get data from neon in "+self.monitorList[i])
                while (len(self.monValue)!=(len(self.monTof)-1)*len(self.monPid)):
                    self.logger.warning("data size doesn't match! please waiting...")
                    time.sleep(10)
                    self.getDataFromNeon(self.monitorList[i], self.neonpathValue[i])
                if self.myDict['running']:
                    try:
                        self.logger.debug("   INFO: createWorkspace"+str(datetime.datetime.now()))
                        self.createWorkspace(self.monitorList[i])
                    except:
                        self.myDict['error']=True
                        self.myDict['running']=False
                        self.logger.error("error in create workspace in"+self.monitorList[i])
                    if self.myDict['running']:
                        try:
                            self.logger.debug("   INFO: dataSet")
                            self.dataSet(self.monitorList[i])
                            shutil.move("./"+self.monitorList[i]+".nxs","./tmp/"+self.monitorList[i]+".nxs")
                        except:
                            self.myDict['error']=True
                            self.myDict['running']=False
                            self.logger.error("error in set data in "+self.monitorList[i])
                    else:
                        pass
                else:
                    pass
        else:
            pass

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

