import socket
import struct
import math
from time import sleep

global option

global SOCKET_OPT
global MCAST_GRP
global PORT
global ENDPNT_ADDR
global FPS

SOCKET_OPT = 2
MCAST_GRP = '239.192.1.1'
PORT = 5432
ENDPNT_ADDR = '127.0.0.1'
FPS = 24

def menu():
	print("###################################")
	print()
	print("[1] Unicast (1) or multicast (2)? (Default is Multicast)")
	print("[2] Set Mutlicast Address (Default is 239.192.1.1)")
	print("[3] Set Port (Default is 5432)")
	print("[4] Set endpoint Address (Default is 127.0.0.1)")
	print("[5] Set FPS (Default is 24)")
	print("[6] Print all current Settings")
	print("[7] Send Metadata (CTRL + C to end)")
	print("[0] EXIT")
	print()
	print("###################################")

	global option
	option = int(input("What would you like to do?: "))

	while option !=0:
		if option == 1:
			setSocketType()
		elif option == 2:
			setMulticast()
		elif option == 3:
			setPort()
		elif option == 4:
			setEndpointAddress()
		elif option == 5:
			setFPS()
		elif option == 6:
			printSettings()
		elif option == 7:
			sendData()
		else:
			print("invalid option")


def sendData():

	jsonMessagePt1 = '{"camera":{"state":{"health":"good","majorState":"IDLE"},"device":{"model":"UMC-4","umc4SerialNumber":"K2.0000642-7201","umc4SoftwareVersion":"2.3","cameraSerialNumber":"33454","cameraSoftwarePackageName":"7.1.0","cameraSoftwarePackageVersion":"7.1.0"},"optic":{"converter":{"converterFocalLenMultiplier":0,"converterLightLossFactor":0,"converterModel":"","converterPhysicalLength":0,"converterSerialNumber":""},"filter":{"ndFilterDensity":0},"lens":{"lensDevice":{"lensModel":"Fujinon Alura AZ15.5-45 T2.8","lensSerialNumber":"23359","lensMotorRawEncoderLimitsFocus":{"min":-1,"max":-1},"lensMotorRawEncoderLimitsIris":{"min":-1,"max":-1},"lensMotorRawEncoderLimitsFL":{"min":-1,"max":-1}},"lensState":{"lensFocusDistanceImperial":680272,"lensFocusDistanceMetric":'
	jsonMessagePt2 = ',"lensIris":'
	jsonMessagePt3 = ',"lensFocalLength":'
	jsonMessagePt4 = ',"lensScaleRawEncoderValueFocus":805,"lensScaleRawEncoderValueIris":3123,"lensScaleRawEncoderValueFL":1174,"lensMotorRawEncoderValueFocus":-1,"lensMotorRawEncoderValueIris":-1,"lensMotorRawEncoderValueFL":-1}}},"sensor":{"sensorState":{"shutterAngle":5.36954e+06,"exposureTime":"1000/60000","exposureIndex":800,"sensorSampleRate":"30000/1000"}},"recording":{"medium":{"remainingCapacity":0},"projectRate":{"timebase":"24000/1000","dropframe":false},"acquisitionTimestamp":1327494,"clip": {"slateInfo":{"cameraIndex":"A"}}},"processing":{"whiteBalance":{"colorTemperature":6500,"whiteBalanceTint":0}},"positional":{"orientation":{"tilt":0.2,"roll":-41.2}}}}'

	HOURS = 00
	MINUTES = 00
	SECONDS = 00
	FRAMES = 00
	
	INDEX = 1
	MasterTC = str(HOURS) + ":" + str(MINUTES) + ":" + str(SECONDS) + ":" + str(FRAMES)
	CameraIndex = 'A'
	LensName = 'MetadataEncoder'
	LensDistanceUnit = "Meter"
	FocusDistance = 200
	LensFocalLength = 25000
	LensIris = " T2  + 2/10"
	LensLinearIris = 5000
	RawEncoderFocus = 0
	RawEncoderFocal = 0
	RawEncoderIris = 0
	EncoderLimFocusMotorMin = 0
	EncoderLimFocusMotorMax  = 0
	EncoderLimFocalMotorMin = 0
	EncoderLimFocalMotorMax = 0
	EncoderLimIrisMotorMin = 0
	EncoderLimIrisMotorMax = 0
	Tilt = -0.7
	Roll = 0.5
	TAB = "\t"
	NEWLINE = "\n"

	if SOCKET_OPT == 2:

		sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
		sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
		sock.connect((ENDPNT_ADDR, PORT))

		x = 1
		y = 1
		while True:

			if x<250:
				LensLinearIris += x/10
				FocusDistance += x/10
				LensFocalLength += x

				if y < FPS:
					FRAMES = y
				else:
					FRAMES = y%FPS

				if y%FPS == 0:
					SECONDS += 1

				if SECONDS%60 == 0 and SECONDS != 0:
					SECONDS = 0
					MINUTES += 1

				if MINUTES%60 == 0 and MINUTES !=0:
					MINUTES = 0
					HOURS += 1

				MasterTC = str(HOURS) + ":" + str(MINUTES) + ":" + str(SECONDS) + ":" + str(FRAMES)
				message = jsonMessagePt1 + str(FocusDistance) + jsonMessagePt2 + str(LensLinearIris) + jsonMessagePt3 + str(LensFocalLength) + jsonMessagePt4;
				byt = message.encode()

				sock.sendto(byt, (MCAST_GRP, PORT))
				#print(LensLinearIris)
				print(LensFocalLength)
				sleep(1.0/FPS)

			else:
				x = 1
				LensLinearIris = 5000
				FocusDistance = 200
				LensFocalLength = 25000

			x+=1
			y+=1

	elif SOCKET_OPT == 1:

		sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

		x = 1
		y = 1
		while True:

			if x<250:
				LensLinearIris += x/10
				FocusDistance += x/100
				LensFocalLength += x/1000

				if y < FPS:
					FRAMES = y
				else:
					FRAMES = y%FPS

				if y%FPS == 0:
					SECONDS += 1

				if SECONDS%60 == 0 and SECONDS != 0:
					SECONDS = 0
					MINUTES += 1

				if MINUTES%60 == 0 and MINUTES !=0:
					MINUTES = 0
					HOURS += 1

				MasterTC = str(HOURS) + ":" + str(MINUTES) + ":" + str(SECONDS) + ":" + str(FRAMES)
				message = jsonMessagePt1 + str(FocusDistance) + jsonMessagePt2 + str(LensLinearIris) + jsonMessagePt3 + str(LensFocalLength) + jsonMessagePt4;
				byt = message.encode()

				sock.sendto(byt, (ENDPNT_ADDR, PORT))
				#print(LensLinearIris)
				print(LensFocalLength)
				sleep(1.0/FPS)

			else:
				x = 1
				LensLinearIris = 5000
				FocusDistance = 20
				LensFocalLength = 25.0

			x+=1
			y+=1
		

def setSocketType():
	print()
	print("###################################")
	global SOCKET_OPT
	SOCKET_OPT = int(input("Input 1 for Unicast and 2 for Multicast: "))
	if SOCKET_OPT == 1:
		print("Socket set to Unicast")
		print("###################################")
		print()
		menu()
	elif SOCKET_OPT == 2:
		print("Socket set to Multicast")
		print("###################################")
		print()
		menu()
	else:
		print("invalid option")
		menu()


def setMulticast():
	print()
	print("###################################")
	global MCAST_GRP 
	MCAST_GRP = str(input("Input Multicast Address: "))
	print("Multicast Address set to: ", MCAST_GRP)
	print("###################################")
	print()
	menu()

def setFPS():
	print()
	print("###################################")
	global FPS
	FPS = int(input("Input FPS: "))
	print("FPS set to: ", FPS)
	print("###################################")
	print()
	menu()

def setEndpointAddress():
	print()
	print("###################################")
	global ENDPNT_ADDR
	ENDPNT_ADDR = str(input("Input Endpoint Address: "))
	print("Endpoint Address set to: ", ENDPNT_ADDR)
	print("###################################")
	print()
	menu()

def setPort():
	print()
	print("###################################")
	global PORT
	PORT = int(input("Input Port: "))
	print("Port set to: ", PORT)
	print("###################################")
	print()
	menu()

def printSettings():
	print()
	print("###################################")
	print("Multicast Address: ", MCAST_GRP)
	print("Endpoint Address: ", ENDPNT_ADDR)
	print("Port: ", PORT)
	print("FPS: ", FPS)
	print("###################################")
	print()
	menu()

menu()