'''
Created on Feb 27, 2012
Modified on May 18, 2012
@version: 0.1
@author: Dilum Bandara
@email: dilumb@engr.colostate.edu
@license: Apache License v2.0

   Copyright 2012 H. M. N. Dilum Bandara and Anura P. Jayasumana, Colorado State
   University

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
'''

class USubscription(object):
    '''
    User query subscription class
    '''


    def __init__(self, query, validTime, interval, queryTime):
        '''
        Constructor
        @param query: Query 
        @param validTime: Query response need to be fresher than this
        @param interval: Inter-arrival time for query of this subscription
        @param queryTime: Time query was issued  
        '''
        self.query = query
        self.validTime = validTime
        self.interval = interval
        self.queryTime = queryTime
        self.nextValidTime = validTime + interval
        self.answerTime = -1 #Time that query was answered
        self.genTime = 999999.9 #When was data generated
        self.totalData = 0 #Total data size
        self.hops = -1 #Hops for data message 
        self.subInter = {} #Sub interests
        self.numSubAnswer = 0 #Number of sub-interests answered
        self.firstRound = True


    def prepareNextRound(self):
        '''
        Reset counters for next round
        '''
        self.validTime = self.nextValidTime
        self.nextValidTime += self.interval #Current + interval
        self.queryTime += self.interval
        self.answerTime = -1
        self.genTime = 999999.9 
        self.totalData = 0
        self.hops = -1
        for i in self.subInter: self.subInter[i] = 0
        self.numSubAnswer = 0
        self.firstRound = False #No longer 1st round


    def addSubInter(self, subQueries):
        '''
        Track sub-interests
        @param subQueries: Sub-queries in interest messages 
        '''
        for i in range(len(subQueries)):
            self.subInter[subQueries[i][0]] = 0


    def updateValidTime(self, nextQueryTime, newInterval, newDelay):
        '''
        Updated valid time of this subscription based on new valid time
        @param newQueryTime: When will next query be issued
        @param newInterval: Interval that queries are generated 
        @param newDelay: Delay time for those queries
        '''
#        assert(nextQueryTime - newDelay <= self.nextValidTime), \
#                str(nextQueryTime) + '\t' + str(newDelay) + '\t' + \
#                str(self.nextValidTime) + '\t' + self.query
        if nextQueryTime - newDelay > self.nextValidTime: return
        maxAlpha = self.interval/newInterval
        newTime = self.validTime
        for i in range(maxAlpha + 1):
            if nextQueryTime - newDelay + i * newInterval >self.nextValidTime:
                newTime = nextQueryTime - newDelay + newInterval * (i - 1)
                break
        if self.validTime > newTime:
            if self.firstRound == False: 
                self.validTime = newTime #push back
                self.nextValidTime = newTime + self.interval #Set next time
                return
        #1st round or self.validTime <= newTime
        if self.nextValidTime > newTime: #Push back next time
            self.nextValidTime = newTime 


    def handleData(self, subQuery, genTime, dataSize, hops, currentTime):
        '''
        Handle data received for sub-interests
        @param subQuery: Sub-query in interest message
        @param genTime: Time that data for interest message was generated
        @param dataSize: Data size
        @param hops: Hops
        @param currentTime: Current time 
        @return: Was all subscriptions answered (True/False) 
        '''
        if self.subInter[subQuery] == 1: return False #Already in, not useful
        if self.validTime > genTime: return False #Too old
        self.subInter[subQuery] = 1 #Received
        self.totalData += dataSize
        if self.hops < hops: self.hops = hops
        if self.genTime > genTime: self.genTime = genTime            
        self.numSubAnswer += 1
        if self.numSubAnswer == len(self.subInter): #Found all 
            self.answerTime = currentTime
            return True
        return False
