import config
import datetime 
import StringIO
import subprocess
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 
from face_client import FaceClient
from person import Person
from mouth_function import saySomething
import pickle
import time
import os
import keyring
import sys
import math

#---------Motion detection and face recognition-----------
		
# Capture a small test image (for motion detection)
# Keep image in RAM until we need to do face recognition
def captureTestImage():
	command = "raspistill -w %s -h %s -t 1 -n -vf -e bmp -o -" % (100, 75)
	imageData = StringIO.StringIO()
	imageData.write(subprocess.check_output(command, shell=True))
	imageData.seek(0)
	im = Image.open(imageData)
	buffer = im.load()
	imageData.close()
	return im, buffer

# Probe Sky Biometry for Face recognization
def recognizeFace(theImg,filenameFull):
	font = ImageFont.truetype("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf", 14)
	theFileLocation =  "http://" + config.publicIP + "/temp.jpg"
	client = FaceClient(keyring.get_password('skybio','api_key'),keyring.get_password('skybio','api_secret'))
	img = Image.open(theImg)
	width, height = img.size
	draw = ImageDraw.Draw(img)
	print theFileLocation
	photo = client.faces_recognize('all',theFileLocation, namespace = 'python')
	print photo
	# Number of people in photo
	numFaces = len(photo['photos'][0]['tags'])
	print "Detected " + str(numFaces) + " faces."
	textCaption = ""
	iii=0
	theSpeech = ""
	while iii<numFaces:
		for person in config.personList:
#		for j, person in enumerate(personList):
			try:
				theId = photo['photos'][0]['tags'][iii]['uids'][0]['uid']
				foundName = theId
				print "I see " + foundName
				xPos = width*(int(photo['photos'][0]['tags'][iii]['eye_right']['x']))/100
				yPos = height*(int(photo['photos'][0]['tags'][iii]['eye_right']['y']))/100
				if person.name in foundName: #and photo['photos'][0]['tags'][iii]['attributes']['gender']['value'] == person.gender:
					theSpeech = theSpeech + "%s" % person.greeting
					
					timeDifference = datetime.datetime.now() - person.lastSeen
					person.lastSeen = datetime.datetime.now()
					#personList[j].lastSeen = person.lastSeen
					days = math.floor(timeDifference.total_seconds() / 60 / 60 / 24)
					hours = math.floor(timeDifference.total_seconds() / 60 / 60	)	
					minutes = math.floor(timeDifference.total_seconds() / 60 )	
					if days > 0:
						theSpeech = theSpeech + "It's been %d days since I have seen you, %s. " % (days,person.name)
					elif hours > 4:
						theSpeech = theSpeech +  "It's been %d hours since I have seen you, %s. " % (hours,person.name)
					elif minutes > 0:
						theSpeech = theSpeech +  "It's been %d minutes since I have seen you, %s. " % (minutes,person.name)
					draw.text((xPos, yPos),person.name,(255,255,0),font=font)
					draw.text((0, 0),time.strftime("%c"),(255,255,0),font=font)
					collection = ['eyes','sadness','mood','glasses']
					for x in collection:
						try:
							eyes = photo['photos'][0]['tags'][iii]['attributes'][x]['value']
							conf = photo['photos'][0]['tags'][iii]['attributes'][x]['confidence']
							if conf > 20:
								print " " + x + " = " + eyes
								yPos = yPos + 20
								draw.text((xPos, yPos)," " + x + ": " + eyes,(255,255,0),font=font)
								if x == 'mood':
									theSpeech = theSpeech + "Why are you " + eyes + "? "		
						except:
							print "No " + x
			except:
				print "Error locating face in person database."
				print "Unexpected error:", sys.exc_info()[0]
				raise
		iii = iii + 1
	
	if len(theSpeech)>2: # proxy for if something happened
		img.save(filenameFull)
		img.save("/var/www/face.jpg")
		pickle.dump(config.personList, open("ai_data/personlist.p","wb") )
	return theSpeech

# Check whether a face has been seen recently
def seenAFaceInAwhile():
	# first check if anybody has been seen
	hasSeenSomeone = 0
	for person in config.personList:
		timeDifference = datetime.datetime.now() - person.lastSeen
		#personList[j].lastSeen = person.lastSeen
		days = round(timeDifference.total_seconds() / 60 / 60 / 24)
		hours = round(timeDifference.total_seconds() / 60 / 60	)	
		minutes = round(timeDifference.total_seconds() / 60 )	
		if minutes<10 and days < 1 and hours < 1:
			hasSeenSomeone = 1
	return hasSeenSomeone
	
# Save a full size image to disk
def saveImage():
	keepDiskSpaceFree(config.diskSpaceToReserve)
	time = datetime.datetime.now()
	filenameFull = config.filepath + config.filenamePrefix + "-%04d%02d%02d%02d%02d%02d" % (time.year, time.month, time.day, time.hour, time.minute, time.second)+ "." + config.fileType
	
	# save onto webserver
	filename = "/var/www/temp.jpg"
	subprocess.call("sudo raspistill -w "+ str(config.saveWidth) +" -h "+ str(config.saveHeight) + " -t 1 -n -vf -e " + config.fileType + " -q 15 -o %s" % filename, shell=True)
	print "Captured image: %s" % filename

	theSpeech = recognizeFace(filename,filenameFull)
	if len(theSpeech)>2:
		print theSpeech
		saySomething(theSpeech,"en")
		config.lookForFaces = 0


# Keep free space above given level
def keepDiskSpaceFree(bytesToReserve):
	if (getFreeSpace() < bytesToReserve):
		for filename in sorted(os.listdir(".")):
			if filename.startswith(filenamePrefix) and filename.endswith("." + fileType):
				os.remove(filename)
				print "Deleted %s to avoid filling disk" % filename
				if (getFreeSpace() > bytesToReserve):
					return

# Get available disk space
def getFreeSpace():
	st = os.statvfs(".")
	du = st.f_bavail * st.f_frsize
	return du

def lookAtSurroundings(threadName):
	motionDetectedLast = datetime.datetime.now()
	motionDetectedNow = datetime.datetime.now()
	print "Started listening on thread %s" % threadName
	## look at surroundings
	# Get first image
	image1, buffer1 = captureTestImage()
	# Reset last capture time
	lastCapture = time.time()
	while (1):
		# check if CPU intensive processes are running
		output = os.popen("pgrep vlc").read()
		isRunning = 0
		if len(output) > 0:
			isRunning = 1
#		if config.gettingStillImages and config.gettingStillAudio:
#			if config.timeTimeout == 0:
#				config.timeTimeout = 10 
#			print "No one is around, closing eyes for %d seconds" % config.timeTimeout
#			time.sleep(config.timeTimeout)
#			config.gettingStillImages = 0
#			motionDetectedLast = datetime.datetime.now()
		if config.gettingVoiceInput==1:
			time.sleep(6)
		elif isRunning:
			time.sleep(20)
		else:
			# Get comparison image
			image2, buffer2 = captureTestImage()
			pixelSum =  0
			numCountedPixels = 0
			motionHasBeenDetected = False
			# Count changed pixels
			changedPixels = 0
			for x in xrange(0, 100):
				# Scan one line of image then check sensitivity for movement
				for y in xrange(0, 75):
					# Just check green channel as it's the highest quality channel
					pixdiff = abs(buffer1[x,y][1] - buffer2[x,y][1])
					pixelSum += buffer1[x,y][1]
					numCountedPixels += 1
					if pixdiff > config.threshold:
						changedPixels += 1
				# Changed logic - If movement sensitivity exceeded then
				# Save image and Exit before full image scan complete
				if changedPixels > config.sensitivity:   
					lastCapture = time.time()
					print "Motion detected! changedPixels > sensitivity (" + str(changedPixels) + " > " + str(config.sensitivity) + ")"
					motionDetectedLast = datetime.datetime.now()
					motionHasBeenDetected = True
					config.timeTimeout = 0 # reset timeout
					if not seenAFaceInAwhile():
						config.gettingVisualInput = 1
						saveImage() # face detection
						config.gettingVisualInput = 0
					break
				continue	
			print "Changed pixels : " + str(changedPixels)
			if (numCountedPixels>500):
				lightChange = pixelSum / numCountedPixels
				print "Pixel sum : %2.1f" % lightChange
				if (lightChange < 5):
					os.system("echo 'rf a1 on' | nc localhost 1099")
					os.system("echo 'rf c1 on' | nc localhost 1099")
			# Check force capture
			if config.forceCapture:
				if time.time() - lastCapture > config.forceCaptureTime:
					changedPixels = config.sensitivity + 1
			# Swap comparison buffers
			image1  = image2
			buffer1 = buffer2
			timeDifference = datetime.datetime.now() - motionDetectedLast
			minutes = round(timeDifference.total_seconds() / 60 )	
			if timeDifference.total_seconds() > config.videoHangout:
				config.gettingStillImages = 1
			else:
				config.gettingStillImages = 0
			if config.lookForFaces:
				config.gettingVisualInput = 1
				saveImage() # face detection
				config.gettingVisualInput = 0