from math import sqrt

#hight = 132
#width = 135

# Centers for each letter as during swipe recording.
centers = dict({
	'q' : (85, 120),
	'w' : (220, 120),
	'e' : (355, 120),
	'r' : (490, 120),
	't' : (625, 120),
	'y' : (760, 120),
	'u' : (995, 120),
	'i' : (1030, 120),
	'o' : (1165, 120),
	'p' : (1300, 120),

	'a' : (155, 252),
	's' : (290, 252),
	'd' : (425, 252),
	'f' : (560, 252),
	'g' : (695, 252),
	'h' : (830, 252),
	'j' : (965,252),
	'k' : (1100,252),
	'l' : (1235,252),

	'z' : (290, 385),
	'x' : (425, 385),
	'c' : (560, 385),
	'v' : (695, 385),
	'b' : (830, 385),
	'n' : (965, 385),
	'm' : (1100, 385),

	# dummy
	''  : (99999,99999)
	})

# Get the average of a list of pairs, so that is basically the center.
def averagePair(pairList):
	(x, y) = reduce(lambda x, y : (x[0] + y[0], x[1] + y[1]), pairList, (0,0))
	return (int(x/len(pairList)), int(y/len(pairList)))

# Perform some geometry as described in thesis.
def leavesAt((a, b), (c, d)):
	# print (a, b), (c, d)
	width = 135/2
	height = 132/2

	if c-a == 0:
		slope = 999999
	else:
		slope = (d-b) / float((c-a))

	offset = b - slope * a
	# y = slope * x + offset
	if  offset > -1 and offset < 1:
		# hier weten we de x, en moeten we de y weten
		# y = slope * x + offset
		if c > a:
			x = a + width
		else: 
			x = a - width
		y = slope * x + offset
	else:
		# hier weten we de y, en moeten we de x weten
		# x = (y - offset) / slope
		if d > b:
			y = b + height
		else:
			y = b-height

		if slope in [0, 0.0]:
			x = a
		else:
			x = (y-offset) / slope
	return (int(x), int(y))

# Smooths the sequence of coordinates by assuming the user makes shortcuts.
def smoothSequence(word, precision = 32):
	straight = expectedSequence(word)
	smooth = [ straight[0] ]
	for i in xrange(1,len(straight)-1):
		enters = leavesAt(straight[i], straight[i-1])
		leaves = leavesAt(straight[i], straight[i+1])

		averaging = [ straight[i] for _ in xrange(25) ]
		for _ in xrange(1):
			averaging.append(enters)
		for _ in xrange(3):
			averaging.append(leaves)

		smooth.append(averagePair(averaging))

	smooth.append(straight.pop())
	return fillWithMaxDistance(smooth, precision)

# The most simple expected sequence for a word, just the ordered list of letter centers.
def expectedSequence(word):
	lastChar = ''
	noDoubles = ''
	for letter in word:
		if not letter == lastChar:
			noDoubles += letter
		lastChar = letter
	global centers
	return [ centers[letter] for letter in noDoubles ]


# Fills a sequence of pairs by adding additional pairs such that there is no large distance between any two sequential pairs
def fillWithMaxDistance(path, maxDistance=200):
	def distance((x,y),(i,j)):
		return sqrt( (x-i)**2 + (y-j)**2 )
	def middle((x,y),(i,j)):
		return ((x+i)/2, (y+j)/2)

	i = 0
	while i+1 < len(path):
		if distance(path[i],path[i+1]) > maxDistance:
			path.insert(i+1, middle(path[i],path[i+1]))
		else:
			i += 1
	return path




