#are the end times in both files the same?? No...user update?

import glob
import re

#GET RUN NAMES
runNames = glob.glob('*.rep')
#GET TRACESTATE OBJECT NAMES
traceObjects = ['BPBerth1','BPBerth2']
#STATES THAT EXIST FOR OCCUPIED -- INCLUDES KICKED OFF BERTH STATES AS WELL
states = ['Wait to Handle','Handling delay - RampUp','Handling','Handling delay - RampDown','Clear Berth',
          'Wait for Conditions to Approach Berth','Wait for Conditions to Clear Berth','Approach Berth','Handling delay - Weather']
notForcedStates = [ 'Wait to Handle','Handling delay - RampUp','Handling','Handling delay - RampDown',
                    'Wait for Conditions to Clear Berth','Handling delay - Weather']
preHandle = 'Pre-Handling Time'
postHandle = 'Post-Handling Time'
#THIS PYTHON FILE NEEDS TO BE IN THE SAME DIRECTORY AS REP AND TRACE STATE FILES
#THIS FILE GRABS RUN NAMES FROM THE REP FILE AND ADDS traceObjects to the end
def main():
    overlapOccupied = 0.0
    Dict1 = []
    Dict2 = []
    Dict3 = []
    data = [[],[]]
    combined = []
    #something in this loop screws up the array, causes the data to create an array within an array
    for run in runNames:
        Dict1 = []
        for i in range(len(traceObjects)):
            with open('./'+run[:-4]+'-'+traceObjects[i]+'.trc') as fread:
                alllines = []
                alllines = fread.readlines()
                for lines in alllines:
                    data[i].append(lines)
                    
        #use to manually check to see if calculations are correct
        writerA = open(run[:-4]+'-Berth1occupied'+'.occ','w')
        writerB = open(run[:-4]+'-Berth2occupied'+'.occ','w')
        temp1 = getOccupiedState(data[0])
        temp2 = getOccupiedState(data[1])
        writeOccupiedState(temp1,writerA)
        writeOccupiedState(temp2,writerB)
        
        Dict3 = getDurationTime(temp1) + getDurationTime(temp2)
        berth1Occupied = getOccupiedTime(Dict3,traceObjects[0])
        berth2Occupied = getOccupiedTime(Dict3,traceObjects[1])

        sortedData = sorted(Dict3)
        
        writerBerth1 = open(run[:-4]+'-asdf.occ','w')
        for lines in sortedData:
            for items in lines:
                writerBerth1.write(str(items)+'\t')
            writerBerth1.write('\n')
        #sort based on start time
        #PERCENTAGE OF TIME THAT BOTH BERTHS ARE OCCUPIED
        for i in range(len(sortedData)):
            #if the two lines are the same berth, cannot overlap
            if i == len(sortedData)-1 or sortedData[i+1][4]=='end' or sortedData[i][0]<8760:
                pass
            elif (sortedData[i][2]==sortedData[i+1][2]):
                pass
            #end1 >= start2 and end2 >= start1: if true: overlap
            elif (sortedData[i][3]>=sortedData[i+1][0] and sortedData[i+1][3]>=sortedData[i][0]):
                #overlap
                #first berth found encapsulates second berth found
                #end2-start2
                if (sortedData[i][3]>=sortedData[i+1][3]):
                    overlapOccupied += sortedData[i+1][3]-sortedData[i+1][0]
                #second berth ends later: end1-start2
                elif (sortedData[i+1][3]>sortedData[i][3]):
                    overlapOccupied += sortedData[i][3]-sortedData[i+1][0]
                else:
                    #because the data is sorted, the other two scenarios cannot happen
                    #error out here
                    print 'some random case'
        writer = open(run[:-4]+'-occupied'+'.trc','w')
        writer.write('Percentage Occupied')
        writer.write('\n'+traceObjects[0]+' Occupied: '+str(berth1Occupied)+'\t'+'%')
        writer.write('\n'+traceObjects[1]+' Occupied: '+str(berth2Occupied)+'\t'+'%')
        writer.write('\n'+'Both Berths Occupied at the same time: '+str(overlapOccupied/sortedData[-1][3]*100)+'\t'+'%')

def getDurationTime(myData):
    timeOccupied = 0.0
    startTime = 0.0
    endTime =0.0
    newEndTime = 0.0
    berthName = ''
    myList = []
    startTimeIndex = 0 #index from getOccupiedState(myData)
    berthNameIndex = 1 #index from getOccupiedState(myData)
    stateNameIndex = 2 #index from getOccupiedState(myData) 
    durationIndex = 3  #index from getOccupiedState(myData)
    endTimeIndex = 4   #index from getOccupiedState(myData)
    OccupiedIndex = 5  #index from getOccupiedState(myData)
    for i in range(len(myData)):
        if i < len(myData)-1:
            if not myData[i][OccupiedIndex] and myData[i+1][OccupiedIndex]:
                #DO NOTHING
                #timeOccupied += float(i[durationIndex])
                startTime = float(myData[i+1][startTimeIndex])
                berthName = myData[i+1][berthNameIndex]
            elif not myData[i][OccupiedIndex] and not myData[i+1][OccupiedIndex]:
                #DO NOTHING
                timeOccupied = 0
            elif myData[i][OccupiedIndex] and myData[i+1][OccupiedIndex]:
                timeOccupied += float(myData[i][durationIndex])
            elif myData[i][OccupiedIndex] and not myData[i+1][OccupiedIndex]:
                endTime = float(myData[i][endTimeIndex])
                timeOccupied += float(myData[i][durationIndex])
                myList.append([startTime,berthName,timeOccupied,startTime+timeOccupied,endTime])
                timeOccupied=0
            else:
                print '\n\nSOMETHING WRONG\n\n'
        else:
            if myData[i][OccupiedIndex] and myData[i-1][OccupiedIndex]:
                timeOccupied += float(myData[i][durationIndex])
                myList.append([startTime,berthName,timeOccupied,startTime+timeOccupied,'end'])
            else:
                myList.append([myData[i][startTimeIndex],myData[i][berthNameIndex],myData[i][OccupiedIndex],myData[i][startTimeIndex]+myData[i][durationIndex],'end'])
    return myList

#AS LONG AS parseData(data) IS USED, DATA WILL BE IN THE FORMAT BELOW TO ADD UP TIME OCCUPIED AND DIVIDE BY END TIME ( END TIME = START TIME + DURATION )
#CHECK END TIME FOR THE LAST TWO LINES TO SEE WHICH ONE ENDS LATER..MAYBE THIS SHOULD BE MANUAL?
def getOccupiedTime(myData, myObject):
    sumOccupied = 0.0
    for i in myData:
        if (isinstance(i[0], float) and i[1] == myObject and (i[4] != 'end' and i[0]>=8760)):
            sumOccupied += i[2]
    lastLine = myData[-1]
    percentOccupied = sumOccupied/(lastLine[3])*100
    return percentOccupied
            
def getOccupiedState(myData):
    myDict = []
    Occupied = False
    startTime = 0.0 
    duration = 0.0
    endTime = 0.0
    berthName = ''
    stateName = ''
    for i in range(len(myData)):
        searchStates = re.match('([0-9.]+)  (BPBerth[12]).setState\( "([a-zA-Z -0-9]+)" \) dt = ([0-9.]+)',myData[i])
        if searchStates and searchStates.group(1)>=8760:
            startTime = float(searchStates.group(1))
            berthName = searchStates.group(2)
            stateName = searchStates.group(3)
            duration = float(searchStates.group(4))
            endTime = startTime+duration
            if (searchStates.group(3)==preHandle): 
                Occupied = True
                myDict.append([startTime,berthName,stateName,duration,endTime,Occupied])  
            elif (Occupied and ((searchStates.group(3)==postHandle) or (searchStates.group(3)==states[6]))):
                searchConditions = re.match('([0-9.]+)  (BPBerth[12]).setState\( "([a-zA-Z -0-9]+)" \) dt = ([0-9.]+)',myData[i+1])
                if (searchConditions and searchConditions.group(3)==states[4]):
                    myDict.append([startTime,berthName,stateName,duration,endTime,Occupied]) 
                    Occupied = False
                else:
                    myDict.append([startTime,berthName,stateName,duration,endTime,Occupied])  
                    Occupied = True
            elif (searchStates.group(3)==states[6]):
                myDict.append([startTime,berthName,stateName,duration,endTime,Occupied])   
                Occupied = False
            elif (Occupied and (searchStates.group(3) in states)):
                myDict.append([startTime,berthName,stateName,duration,endTime,Occupied])
            elif (searchStates.group(3) in notForcedStates):
                Occupied = True
                myDict.append([startTime,berthName,stateName,duration,endTime,Occupied])
            elif (i==len(myData)-1):
                myDict.append([startTime,berthName,stateName,duration,endTime,Occupied])
                occupied = False
            else:
                Occupied = False
                myDict.append([startTime,berthName,stateName,duration,endTime,Occupied])
    return myDict

def writeOccupiedState(myData,myWriter):
    for line in myData:
        for items in line:
            myWriter.write(str(items)+'\t')
        myWriter.write('\n')



##==============DEPRECATED==============
###create temporary data to add times up
###TRACE STATE FILES ARE ALWAYS OUTPUT IN THE REGEX BELOW -- UPDATE IF THE OUTPUT CHANGES
##def parseData(data):
##    timeOccupied = 0.0
##    startTime = 0.0
##    endTime = 0.0
##    #newEndTime used to check to make sure the math is correct
##    newEndTime = 0.0
##    berth = ''
##    occupied = False
##    myDict = [['Time','Berth','Duration','EndTime','TimeEndTime']]
##    for i in range(len(data)):
##        searchFound = re.match('([0-9.]+)  (BPBerth[12]).setState\( "([a-zA-Z -0-9]+)" \) dt = ([0-9.]+)',data[i])
##        if searchFound and (float(searchFound.group(1))>=8760.0):
##            if i != len(data)-1:
##                searchNextLine = re.match('([0-9.]+)  (BPBerth[12]).setState\( "([a-zA-Z -0-9]+)" \) dt = ([0-9.]+)',data[i+1])
##                if (searchNextLine and (searchFound.group(2) != searchNextLine.group(2))):
##                    occupied = False
##            if (searchFound.group(3)==preHandle): 
##                if occupied:
##                    timeOccupied += float(searchFound.group(4))
##                else:
##                    timeOccupied = float(searchFound.group(4))
##                    startTime = float(searchFound.group(1))
##                    occupied = True
##                    berth=searchFound.group(2)
##            elif (occupied and ((searchFound.group(3)==postHandle) or (searchFound.group(3)==states[6]))):
##                searchConditions = re.match('([0-9.]+)  (BPBerth[12]).setState\( "([a-zA-Z -0-9]+)" \) dt = ([0-9.]+)',data[i+1])
##                if (searchConditions and searchConditions.group(3)==states[4]):
##                    occupied = False
##                    myDict.append([startTime,berth,timeOccupied,startTime+timeOccupied,newEndTime])
##                    newEndTime = float(searchFound.group(1)) + float(searchFound.group(4))
##                else:
##                    timeOccupied += float(searchFound.group(4))                    
##            elif (occupied and (searchFound.group(3) in states)):
##                timeOccupied += float(searchFound.group(4))
##            elif (searchFound.group(3) in notForcedStates):
##                timeOccupied += float(searchFound.group(4))
##            if (i==len(data)-1 and (searchFound.group(3) in states) and occupied):
##                myDict.append([startTime,berth,timeOccupied,startTime+timeOccupied,newEndTime])
##                occupied = False
##                myDict.append([float(searchFound.group(1)),searchFound.group(2),float(searchFound.group(4)),float(searchFound.group(1))+float(searchFound.group(4)),'end'])
##            elif (i==len(data)-1):
##                myDict.append([float(searchFound.group(1)),searchFound.group(2),float(searchFound.group(4)),float(searchFound.group(1))+float(searchFound.group(4)),'end'])
##                occupied = False
##    return myDict
