class JSONFileReader():

    def run(self, port, filename):
        self.port = port
        self.outqueuebuffers = {}
        self.outqueues = {}
        self.senders = {}
        self.channels = None
        self.senderParent = SenderParent(self.port, self)

        with open(filename) as f:
            content = f.readlines()

        counter = 0
        while(True):
            if counter >= len(content):
                counter = 0
            message = json.loads(content[counter][:-1])
            self.setData(message)
            counter += 1

    def getData(self, port):
        if len(self.outqueues[port]) > 0:
            return self.outqueues[port].popleft()
        else:
            return None

    def setData(self, message):
        # first time round - can't start senders till we establish the channels
        if not self.channels:
            self.channels = message["channelnames"]
            self.channeltypes = message["channeltypes"]
            for i in range(0, len(message["channelnames"])):
                self.outqueues[i] = deque([], 10000)
                self.senders[i] = ChildDataSender(i, self)
                self.senders[i].start()

            self.senderParent.start()

        # print "data length is", len(message["data"])
        for i in range(0, len(message["data"])):
            thisTime = message["data"][i][0]
            vals = message["data"][i][1]

            for j in range(0, len(self.channels)):
                self.outqueues[j].append(str(vals[j]))
                self.senders[j].dataReady()
            if i < len(message["data"])-2:
                nextTime = message["data"][i+1][0]
                time.sleep(nextTime-thisTime)
            else:
                break

    def getMultiStream(self, queryString):
        if self.senders.has_key(int(queryString)):
            return self.senders[int(queryString)]
        return None
class MultiCollectorSine():
    
    def run(self,port,frequency):
        self.port = port
        self.lastTimes = {}
        self.senders ={}
        self.senderParent=SenderParent(self.port,self)
        self.senderParent.start()        
        self.senderLock=Lock()

        self.curValue = {}

        timeStart = time.clock()
        self.timePerSample = 1.0/float(frequency)
        numSamples=0
        nextTime=timeStart+self.timePerSample
        
        while True:
            curTime=time.clock()
            nextTime+=self.timePerSample
            if curTime<nextTime:
                time.sleep(nextTime-curTime)
            with self.senderLock:
                self.doneSending={}
                for c in self.senders.values():
                    c.dataReady()

    def getMultiStream(self,queryString):
        print queryString
        with self.senderLock:
            if self.senders.has_key(queryString):
                return self.senders[queryString]
            else:
                self.curValue[int(queryString)] = 0
                sender=ChildDataSender(len(self.senders),self)
                self.senders[queryString]=sender
                sender.start()
                return sender

    def getData(self,port):
        curTime=time.clock()
        if not self.lastTimes.has_key(port):
            self.lastTimes[port]=time.clock()
        if curTime - self.lastTimes[port] > self.timePerSample:
                self.lastTimes[port]+=self.timePerSample
                rand = self.getNextVal(port) #random.random() #randint(0,200)-100
                return str(rand)
        return None

    def getNextVal(self, port):
        val = math.sin(math.radians(self.curValue[port]))
        val = (val+1.0)/2.0
        self.curValue[port] += 1
        if self.curValue[port] > 359:
            self.curValue[port] = 0
        return val
    def run(self,port,frequency):
        self.port = port
        self.lastTimes = {}
        self.senders ={}
        self.senderParent=SenderParent(self.port,self)
        self.senderParent.start()        
        self.senderLock=Lock()
        self.out = {}
        
        filename = "noisecollectorout.csv"
        try:
            self.f = open(filename, 'w')
            self.f.write("Happy,Angry,Fear,Surprise,Sad,Disgust\n")
            print "written to file"
        except:
            print "Error opening", filename
        

        timeStart = time.clock()
        self.timePerSample = 1.0/float(frequency)
        numSamples=0
        nextTime=timeStart+self.timePerSample
        
        while True:
            curTime=time.clock()
            nextTime+=self.timePerSample
            if curTime<nextTime:
                time.sleep(nextTime-curTime)
            with self.senderLock:
                self.doneSending={}
                for c in self.senders.values():
                    c.dataReady()
    def run(self, port, channel, latency, bufferSize):
        self.mutex = Lock()
        self.port = port
        self.outqueuebuffers = {}
        self.outbuffers = {}
        self.senders = {}
        self.channels = None
        self.senderParent=SenderParent(self.port,self)
        self.channel = channel
        self.buffer_size = bufferSize
        self.timestamp_buffer = [None] * self.buffer_size
        self.debug = False

        self.index = 0;
        self.offset = None
        self.latency = latency
        self.setupDone = False
        self.channel_count = 0

        pubnub = Pubnub("pub-c-e655613e-f776-4301-9f29-f71edbcd6559",
                        "sub-c-2eafcf66-c636-11e3-8dcd-02ee2ddab7fe",
                        "sec-c-ZjUwZDgzMTItYzE2Mi00ZGYyLTg2NGMtNmE5N2Q3MGI0MTli",
                        False)

        

        while(True):
            
            pubnub.subscribe({
                'channel': self.channel,
                'callback': self.setData
                })
    def run(self, port, filename):
        self.port = port
        self.outqueuebuffers = {}
        self.outqueues = {}
        self.senders = {}
        self.channels = None
        self.senderParent = SenderParent(self.port, self)

        with open(filename) as f:
            content = f.readlines()

        counter = 0
        while(True):
            if counter >= len(content):
                counter = 0
            message = json.loads(content[counter][:-1])
            self.setData(message)
            counter += 1
    def run(self,port,frequency):
        self.port = port
        self.lastTimes = {}
        self.senders ={}
        self.senderParent=SenderParent(self.port,self)
        self.senderParent.start()        
        self.senderLock=Lock()

        timeStart = time.clock()
        self.timePerSample = 1.0/float(frequency)
        numSamples=0
        nextTime=timeStart+self.timePerSample
        
        while True:
            curTime=time.clock()
            nextTime+=self.timePerSample
            if curTime<nextTime:
                time.sleep(nextTime-curTime)
            with self.senderLock:
                self.doneSending={}
                for c in self.senders.values():
                    c.dataReady()
class BrownNoiseMultiCollector():
    
    def run(self,port,frequency):
        self.port = port
        self.lastTimes = {}
        self.senders ={}
        self.senderParent=SenderParent(self.port,self)
        self.senderParent.start()        
        self.senderLock=Lock()
        self.out = {}
        
        filename = "noisecollectorout.csv"
        try:
            self.f = open(filename, 'w')
            self.f.write("Happy,Angry,Fear,Surprise,Sad,Disgust\n")
            print "written to file"
        except:
            print "Error opening", filename
        

        timeStart = time.clock()
        self.timePerSample = 1.0/float(frequency)
        numSamples=0
        nextTime=timeStart+self.timePerSample
        
        while True:
            curTime=time.clock()
            nextTime+=self.timePerSample
            if curTime<nextTime:
                time.sleep(nextTime-curTime)
            with self.senderLock:
                self.doneSending={}
                for c in self.senders.values():
                    c.dataReady()
                    
    def brownNoise(self,val):
        q = random.random()
        if q > 0.5:
            val = val + ((1-q)/5)
            if val > 1.0:
                return val - (2*((1-q)/10))
        else:
            val = val - ((q)/5)
            if val < 0.0:
                return val + (2*((q)/10))
        return val
            
    
    def getMultiStream(self,queryString):
        print queryString
        with self.senderLock:
            if self.senders.has_key(queryString):
                return self.senders[queryString]
            else:
                sender=ChildDataSender(len(self.senders),self)
                self.senders[queryString]=sender
                self.out[queryString] = 0.5
                sender.start()
                return sender
            
    def getData(self,port):
        curTime=time.clock()
        if not self.lastTimes.has_key(port):
            self.lastTimes[port]=time.clock()
        if curTime - self.lastTimes[port] > self.timePerSample:
            self.lastTimes[port]+=self.timePerSample
            if len(self.out) > 0:
                self.out[str(port)] = self.brownNoise(self.out[str(port)])
                if port == 5:
                    for i in range(0,len(self.out)):
                        self.f.write(str(self.out[str(i)]))
                        if i < len(self.out)-1:
                            self.f.write(",")
                    self.f.write("\n")
                return str(self.out[str(port)])
        return None
class PubnubCollector():

    def run(self, port, channel, latency, bufferSize):
        self.mutex = Lock()
        self.port = port
        self.outqueuebuffers = {}
        self.outbuffers = {}
        self.senders = {}
        self.channels = None
        self.senderParent=SenderParent(self.port,self)
        self.channel = channel
        self.buffer_size = bufferSize
        self.timestamp_buffer = [None] * self.buffer_size
        self.debug = False

        self.index = 0;
        self.offset = None
        self.latency = latency
        self.setupDone = False
        self.channel_count = 0

        pubnub = Pubnub("pub-c-e655613e-f776-4301-9f29-f71edbcd6559",
                        "sub-c-2eafcf66-c636-11e3-8dcd-02ee2ddab7fe",
                        "sec-c-ZjUwZDgzMTItYzE2Mi00ZGYyLTg2NGMtNmE5N2Q3MGI0MTli",
                        False)

        

        while(True):
            
            pubnub.subscribe({
                'channel': self.channel,
                'callback': self.setData
                })

    def getData(self, port):
        if len(self.outqueuebuffers[port]) > 0:
            return self.outqueuebuffers[port].popleft()
        else:
            return None

    def setData(self, message):
        # print "got data"
        #first time round - can't start senders till we establish the channels
        if self.offset is None:
            self.offset = (time.time() - message["data"][0][0]) + self.latency
            self.channel_count = len(message["channelnames"])
            self.channels = message["channelnames"]
            self.channeltypes = message["channeltypes"]
            for i in range(self.channel_count):
                self.outbuffers[i] = [None] * self.buffer_size
                self.outqueuebuffers[i] = deque([], 1000)
                self.senders[i] = ChildDataSender(i, self)
                self.senders[i].start()
            if self.debug:
                print "Got Data:", len(self.outbuffers)            
            self.senderParent.start()
            # print "finished initial setup"
        self.mutex.acquire()

        for i in range(len(message["data"])):

            self.timestamp_buffer[self.index] = message["data"][i][0]
            vals = message["data"][i][1]

            for j in range(len(vals)):
                self.outbuffers[j][self.index] = vals[j]

            self.index += 1
            if self.index >= self.buffer_size:
                self.index = 0

        self.mutex.release()

        if not self.setupDone:
            self.delThread = PubNubReceiverDeliveryThread(self)
            self.delThread.start()
            self.setupDone = True
            # print message
            # print "started thread"


        return True


    def getMultiStream(self,queryString):
        if self.senders.has_key(int(queryString)):
            return self.senders[int(queryString)]
        return None