#!/usr/bin/python3

import tkinter as tk
import tkinter.font as tkFont
import time
import math
import sys
import gc

from gps import *

#gpsSess = gps(host="samsungnetbook", mode=WATCH_ENABLE|WATCH_NEWSTYLE)
gpsSess = gps(host="172.25.36.43", mode=WATCH_ENABLE|WATCH_NEWSTYLE)
#gpsSess = gps(host="127.0.0.1", mode=WATCH_ENABLE|WATCH_NEWSTYLE)

# Globals
run = True
window = tk.Tk()
frame = tk.Frame(master = window)
canvas = tk.Canvas(master=frame)

# Index 0 - 5 - 10 == Red - Yellow - Green
segCols = [ "#FF0000", "#FF3300", "#FF6600", "#FF9900", "#FFCC00", "#FFFF00", "#CCFF00", "#99FF00", "#66FF00", "#33FF00", "#00FF00", "#000000" ]
satCols = [ "#FF33BB", "#FF33DD", "#FF33FF", "#CC33FF", "#9933FF", "#6633FF", "#3333FF", "#3366FF", "#3399FF", "#33CCFF", "#33FFFF" ]

# segStrCols[degreesIndx][radiusIndx]
segStrCols = []
for indx in range(24):
	radDefCols =  [ 11 ] * 9
	segStrCols = segStrCols + [ radDefCols ]

font6 = tkFont.Font(size=6, family="Courier")
font7 = tkFont.Font(size=7, family="Courier")
font8 = tkFont.Font(size=8, family="Courier")
font9 = tkFont.Font(size=9, family="Courier")
font12 = tkFont.Font(size=12, family="Courier")
font12B = tkFont.Font(size=12, weight="bold", family="Courier")

###########################################################################################

# Window close button
def closeButton():
	global run
	run = False
	print("Exit requested")
	window.destroy()
	#sys.exit()
	#raise SystemExit

# End closeButton()

###########################################################################################

# Create list of points for segment
def getSegPoints(origX, origY, degStart, degEnd, innerRad, outerRad):
	pointList = []	
	degStart = degStart + 270
	if degStart >= 360: degStart -= 360
	degEnd = degEnd + 270
	if degEnd > 360: degEnd -= 360


	# Start inner clock -> inner anti-clock -> outer anti-clock -> outer clock 
	
	# Inner clockwise
	pointList = pointList + [ origX + (innerRad * math.cos(math.radians(degEnd))) ]
	pointList = pointList + [ origY + (innerRad * math.sin(math.radians(degEnd))) ]

        # Fill in points
	for deg in range(degEnd, degStart, -1):
		pointList = pointList + [ origX + (innerRad * math.cos(math.radians(deg))) ]
		pointList = pointList + [ origY + (innerRad * math.sin(math.radians(deg))) ]

	# Inner anti-clockwise
	pointList = pointList + [ origX + (innerRad * math.cos(math.radians(degStart))) ]
	pointList = pointList + [ origY + (innerRad * math.sin(math.radians(degStart))) ]

	# Outer anti-clockwise
	pointList = pointList + [ origX + (outerRad * math.cos(math.radians(degStart))) ]
	pointList = pointList + [ origY + (outerRad * math.sin(math.radians(degStart))) ]

        # Fill in points
	for deg in range(degStart, degEnd, 1):
		pointList = pointList + [ origX + (outerRad * math.cos(math.radians(deg))) ]
		pointList = pointList + [ origY + (outerRad * math.sin(math.radians(deg))) ]

	# Outer clockwise
	pointList = pointList + [ origX + (outerRad * math.cos(math.radians(degEnd))) ]
	pointList = pointList + [ origY + (outerRad * math.sin(math.radians(degEnd))) ]

	return pointList
	


window.title("Andy's GPS SKY")
window.resizable(False, False)
window.protocol("WM_DELETE_WINDOW", closeButton)
window.geometry("800x800")
window.configure(bg="#DDDDDD")

frame.configure(width=800, height=800, relief=tk.FLAT, borderwidth=0, bg="#DDDDDD")
frame.place(x=0, y=0)

canvas.configure(width=780, height=780, relief=tk.RIDGE, borderwidth=5, bg="#DDDDDD")
canvas.place(x=4, y=4)

outLatErr = 9999.99
outLonErr = 9999.99
outAltErr = 9999.99

#print("About to run")
while run:
	#print("Window updating")
	window.update()

	#print("Top of loop")
	rpt = gpsSess.next()
	#print("Processing data: %s" % (rpt["class"]))
	if rpt["class"] == "GST":
		outLatErr = 9999.99
		outLonErr = 9999.99
		outAltErr = 9999.99
		if "lat" in rpt.keys(): outLatErr = rpt["lat"]
		if "lon" in rpt.keys(): outLonErr = rpt["lon"]
		if "alt" in rpt.keys(): outAltErr = rpt["alt"]

	if rpt["class"] == "SKY":

		for sat in rpt["satellites"]:
			if sat["el"] < 0 or sat["az"] < 0: continue

			# 90 deg shift done when printing
			#degDegs = sat["az"] + 270
			#if degDegs >= 360: degDegs -= 360
			#degIndx = int(degDegs / 15)
			degIndx = int(sat["az"] / 15)
			if degIndx >= 24: degIndx = 23
			if degIndx < 0:
				print("Logic error: degIndx: %d   az: %d" % (radIndx, sat["az"]))

			radIndx = 8 - int(sat["el"] / 10)
			if radIndx < 0: radIndx = 0
			if radIndx > 8: 
				print("Logic error: radIndx: %d   el: %d" % (radIndx, sat["el"]))

			snr = int(sat["ss"] / 5)
			if snr >= 11: snr = 10
			try:
				if snr > segStrCols[degIndx][radIndx] or segStrCols[degIndx][radIndx] == 11: 
					segStrCols[degIndx][radIndx] = snr
					#print("Setting %d %d to %d" % (degIndx, radIndx, snr))
			except:
				print("Exception: 131: degIndx: %d,  radIndx: %d,  el: %d,  az: %d,  snr: %d" % (degIndx, radIndx, sat["el"], sat["az"], snr))

		# Remove old canvas items
		canvas.delete("all")	

		# Add keys
		for indx in range(9):
			canvas.create_rectangle(300 + (indx * 20), 5, 320 + (indx * 20), 25, fill=segCols[indx])
			canvas.create_rectangle(300 + (indx * 20), 25, 320 + (indx * 20), 45, fill=satCols[indx])
		canvas.create_text(160, 15, text="Segment Signal Strengths", fill="#000000", font=font12)
		canvas.create_text(160, 35, text="Satellite Signal Strengths", fill="#000000", font=font12)

		# Draw segments
		for degIndx in range(0, 24):
			deg = degIndx * 15
			for radIndx in range(0, 9):
				rad = radIndx * 40
				canvas.create_polygon(getSegPoints(400, 415, deg, deg + 15, rad, rad + 40), outline="#FFFFFF", fill=segCols[segStrCols[degIndx][radIndx]], width=2)

		# Add satellites
		numUsed = 0
		numSats = 0
		for sat in rpt["satellites"]:
			numSats += 1
			if sat["used"] == True:
				numUsed += 1
			
			degDegs = sat["az"] + 270
			if degDegs >= 360: degDegs -= 360
			centreX = 400 + ((360 - (4 * sat["el"]))  * math.cos(math.radians(degDegs)))
			centreY = 415 + ((360 - (4 * sat["el"]))  * math.sin(math.radians(degDegs)))

			snr = int(sat["ss"] / 5)
			if snr >= 11: snr = 10

			if sat["PRN"] >= 64: 
				if sat["used"]:
					canvas.create_rectangle(centreX - 6, centreY - 6, centreX + 6, centreY + 6, fill=satCols[snr], outline="#FFFFFF", width=3)
				else:
					canvas.create_rectangle(centreX - 6, centreY - 6, centreX + 6, centreY + 6, fill=satCols[snr], outline="#000000", width=3)
			else:
				if sat["used"]:
					canvas.create_oval(centreX - 7, centreY - 7, centreX + 7, centreY + 7, fill=satCols[snr], outline="#FFFFFF", width=3)
				else:
					canvas.create_oval(centreX - 7, centreY - 7, centreX + 7, centreY + 7, fill=satCols[snr], outline="#000000", width=3)

		canvas.create_text(80, 700, fill="#000000", font=font12, text="Satellites\n  %d / %d  \n\n" % (numUsed, numSats))
		canvas.create_text(720, 700, fill="#000000", font=font12, text=" Accuracy\nLat: %.2f\nLon: %.2f\nAlt: %.2f  " % (outLatErr, outLonErr, outAltErr))
