def getParticipantData(timeWindow, emails):
    if emails is not None:  # use test data
        emailList = emails
    else:  # use user data
        emailInput = ui.getEmailAddr()
        emailList = emailInput.split()  # create email list delimited by space character

    participants = list()
    startTimestamp = func.createRfcTimestamp(timeWindow[0])
    endTimestamp = func.createRfcTimestamp(timeWindow[1])

    # Get Google API data
    for idxEmail, eleEmail in enumerate(emailList):  # for each email address (Participant)
        events = list()

        try:
            response = urllib2.urlopen(
                "https://www.googleapis.com/calendar/v3/calendars/"
                + emailList[idxEmail]
                + "/events?timeMin="
                + startTimestamp
                + "&timeMax="
                + endTimestamp
                + "&key=AIzaSyB7IsERaXNIMiRgMAB_tujhdzNVmxpq0KA"
            ).read()
        except urllib2.HTTPError, e:
            print "\nERROR: We could not retrieve the calendar for", emailList[idxEmail]
            print "Please make sure the email address is valid and the calendar is public\n"
            exit(1)

        responseJson = json.loads(response)  # converts to JSON object
        # startTime = responseJson['items'][0]['start']

        # Find Participant's scheduled meetings during timeWindow
        # print responseJson['items'][0]['start']['dateTime']
        # print responseJson['items']
        recurringEvent = list()

        if len(responseJson["items"]) > 0:  # if events exist
            for idxEvent, eleEvent in enumerate(responseJson["items"]):  # for each event
                if (
                    eleEvent["status"] == "confirmed"
                    and "dateTime" in responseJson["items"][idxEvent]["start"]  # ignore cancelled appointments
                ):  # ignore all day events

                    eventStartRfcTimestamp = responseJson["items"][idxEvent]["start"]["dateTime"]
                    eventEndRfcTimestamp = responseJson["items"][idxEvent]["end"]["dateTime"]
                    eventSummary = responseJson["items"][idxEvent]["summary"]
                    email = responseJson["items"][idxEvent]["organizer"]["email"]
                    # print eventStartRfcTimestamp, eventSummary

                    # Convert RFC timestamp to Google timestamp format
                    eventStartGoogleTimestamp = func.rfcToGoogleTimestamp(eventStartRfcTimestamp)
                    eventEndGoogleTimestamp = func.rfcToGoogleTimestamp(eventEndRfcTimestamp)

                    # Determine if event is recurring
                    # If googleTS is < timeWindow start, it's a recurring event. Change event date
                    eventStartPosixTimestamp = func.timeStrToPosix(eventStartGoogleTimestamp)
                    eventEndPosixTimestamp = func.timeStrToPosix(eventEndGoogleTimestamp)
                    timeWindowStartPosix = func.timeStrToPosix(timeWindow[0])
                    timeWindowEndPosix = func.timeStrToPosix(timeWindow[1])
                    if eventStartPosixTimestamp < timeWindowStartPosix:
                        additionalSlots = list()  # if event duration > 30 mins

                        # Add recurring event to each day of the time window
                        timeWindowDays = func.numOfTimeWindowDays(timeWindowStartPosix, timeWindowEndPosix)
                        for i in range(0, timeWindowDays + 1):  # days to add
                            if i == 0:
                                eventStart = func.changeEventDate(timeWindow[0], eventStartGoogleTimestamp)
                                eventEnd = func.changeEventDate(timeWindow[0], eventEndGoogleTimestamp)
                                event = [email, eventSummary, eventStart, eventEnd]
                                events.append(event)
                            else:
                                eventPosix = func.timeStrToPosix(eventStart)
                                eventPosix += 86400  # add one day in seconds
                                eventStart = func.posixToTimeStr(eventPosix)
                                eventEnd = func.changeEventDate(eventStart, eventEndGoogleTimestamp)

                                event = [email, eventSummary, eventStart, eventEnd]
                                events.append(event)
                                # print i, eventStart, eventSummary

                    else:  # event is not recurring
                        event = [email, eventSummary, eventStartGoogleTimestamp, eventEndGoogleTimestamp]
                        events.append(event)

                        # Add additional 30 minute slots
                        # If event duration > 30 mins, add additional 30 min slots
            for idxEvent, event in enumerate(events):
                startTimePosix = func.timeStrToPosix(event[2])
                endTimePosix = func.timeStrToPosix(event[3])
                duration = endTimePosix - startTimePosix

                email = event[0]
                summary = event[1]
                startTime = event[2]
                endTime = event[3]

                if duration > 1800:  # duration > 30 minutes
                    slotCount = int(duration / 1800) - 1  # number of 30 minute slots to add
                    increase = 0
                    for i in range(slotCount):
                        # print 'start = ', startTime, summary
                        posixTime = func.timeStrToPosix(startTime)  # Google TS to Posix
                        increase = increase + 1800
                        posixTime = posixTime + increase  # increment by 30 minutes
                        startTime = func.posixToTimeStr(posixTime)
                        event = [email, summary, startTime, endTime]
                        events.append(event)
                        # print 'end = ', startTime, summary
                    increase = 0

        else:  # no events exists. Participant is available for the entire time window
            event = [eleEmail, None, None, None]
            events.append(event)

            # Sort events by start date
        eventsSorted = sorted(events, key=lambda startDate: startDate[2])

        # print '\n========== Un-Sorted ===================='
        # for idx, ele in enumerate(events):
        # 	print ele[2], ele[1]

        print "\n============ Sorted =================="
        for idx, ele in enumerate(eventsSorted):
            print ele[2], ele[1]

            # Store participant's event data to Participant object
        participants.append(Participant(eventsSorted))
def createMeetingMatrix():	#args are for test suite only
	#print "Test Arg length: ", len(sys.argv)
	#print "Test Args: ", str(sys.argv)
	if len(sys.argv) >= 4:	#run program with test data
		startTimeWindow = str(sys.argv[1])
		endTimeWindow = str(sys.argv[2])
		timeWindowData = google.getTimeWindowData(startTimeWindow, endTimeWindow) #get timeWindow w/ test data

		#Create list of test emails from command line
		emailList = list()
		if len(sys.argv)>= 4:
			for x in range(3, len(sys.argv)):	
				emailList.append(sys.argv[x])	
		participantData = google.getParticipantData(timeWindowData, emailList)
	else:	#run program with user data
		timeWindowData = google.getTimeWindowData(None, None) #get time window data from Google API call

		#Get participants data from Google API call
		participantData = google.getParticipantData(timeWindowData, None)

	# parseGoogleTime returns class object for getday - getYear
	#Parse start and end times of timeWindow provided by Actor and store in object GoogleTime
	timeWindowStart = func.parseGoogleTime(timeWindowData[0])
	timeWindowEnd = func.parseGoogleTime(timeWindowData[1])
	
	#Calculate the number of 30 minute slots in timeWindow
	minutesRange = func.hoursRange(timeWindowStart, timeWindowEnd)
	
	#Create Actor's timeWindow slots for meeting times in Posix format
	timeWindowSlots = func.createTimeSlots(timeWindowStart, timeWindowEnd, 30)
	numOfWindowSlots = len(timeWindowSlots)
	numOfParticipants = len(participantData)

	#Create meeting matrix for each timeWindowSlot and participant
	meetingMatrix = list()	#binary matrix displaying availability for all participants
	for i in range(0, numOfParticipants):	
		meetingMatrix.append('Null')			#initiate matrix to null
	
	idxActor = 0
	idxEvent = 0
	for idxPartpnt, elePartpntm in enumerate(participantData):		#Each participant
		timeSlots = list()	#temp storage for each participant's time slot
		#print '----------------------------'
		#print elePartpntm.getName()
		numOfParticipantSlots = len(participantData[idxPartpnt].getBusyTimeSlot())
		#print 'numOfParticipantSlots = ', numOfParticipantSlots
		if participantData[idxPartpnt].getBusyTimeSlot()[0] is None: #participant available during all timeWindow
			for x in range(0, numOfWindowSlots):		#Actor's desired meeting slots
				timeSlots.append(0)						#participant available during time slot	
			meetingMatrix[idxPartpnt] = timeSlots

		else:	#participant has scheduled events during time window
			while(idxActor < numOfWindowSlots):		#Actor's desired meeting slots
				windowSlot = timeWindowSlots[idxActor]
				participantSlot = participantData[idxPartpnt].getBusyTimeSlot()
	
				#Compare participant's time slot to Actor's desired meeting slots
				#print 'idxEvent = ', idxEvent
				#print 'idxActor = ', idxActor
				if(idxEvent < numOfParticipantSlots):		#Participant time slot
					participantPosix = func.timeStrToPosix(participantSlot[idxEvent])
					#print func.posixToPST(participantPosix)
					#print func.posixToPST(windowSlot)
	
					if(participantPosix == windowSlot):
						#print 'equal'
						timeSlots.append(1)		#participant not available in meeting slot
						idxActor += 1			#next Actor's meeting slot
						idxEvent += 1			#next participant's time slot
						#continue	
	
					if(participantPosix < windowSlot):
						#print 'less'
						timeSlots.append(0)		#participant available in meeting slot
						idxEvent += 1			#next participant's time slot
						#continue	
	
					if(participantPosix > windowSlot):
						#print 'more'
						timeSlots.append(0)		#participant available in meeting slot
						idxActor += 1			#next Actor's meeting slot
						#continue	
	
				#Go to next participant if all participant time slots is checked
				if(idxEvent == numOfParticipantSlots or idxActor == numOfWindowSlots):
					#Set remainding meetingMatrix to 0, indicating participant is available
					for j in range(idxActor, numOfWindowSlots):
						timeSlots.append(0)		#mark remainder as unvailable
	
					idxActor = 0	#reset iterator to first Actor's meeting slot
					idxEvent = 0	#reset iterator to first time slot for next participant
					
					#Store participant availability in meeting matrix
					meetingMatrix[idxPartpnt] = timeSlots
			
					#print meetingMatrix
					break		#got to next participant


	#store meetingMatrix in MeetingAvailability object
	meetingAvailability = MeetingAvailability(meetingMatrix, participantData, numOfWindowSlots, timeWindowSlots)
	#print 'Fun starts here'
	#print meetingAvailability.getMeetingMatrix()
	#print meetingAvailability.getParticipants()
	#print meetingAvailability.getNumOfWindowSlots()
	#print meetingAvailability.getTimeWindowSlots()
	return meetingAvailability