from setting import social_distancing_config as config
from setting.detection import detect_people
from scipy.spatial import distance as dist
import numpy as np
import imutils
import cv2
import os
from tkinter import *
import tkinter as tk
# import filedialog module 
from tkinter import filedialog 

app = Tk()
app.title('Social distancing detector')
app.geometry("400x400") 



input_address = ""
output_address = 'output.avi'
# set display = 1 to display rendering else kept it 0
display = 1



def browsefunc():
	global input_address
	input_address = filedialog.askopenfilename()
	print(input_address)




def generate():
	# load the COCO class labels on which our model is trained
	labelsPath = os.path.sep.join([config.MODEL_PATH, "coco.names"])
	LABELS = open(labelsPath).read().strip().split("\n")


	# receive the paths of YOLO weights and model configuration
	weightsPath = os.path.sep.join([config.MODEL_PATH, "yolov3.weights"])
	configPath = os.path.sep.join([config.MODEL_PATH, "yolov3.cfg"])


	# load our YOLO object detector trained on COCO dataset (80 classes)
	print("Loading YOLO from disk.......")
	net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)


	# check if GPU to be used
	if config.USE_GPU:
		# set CUDA as the preferable backend and target
		print("Setting preferable backend and target to CUDA...")
		net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
		net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)


	# select and check only the *output* layer names that we need from YOLO
	ln = net.getLayerNames()
	ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]


	# initialize the video stream and pointer to output video file
	print("Accessing video stream...")
	vs = cv2.VideoCapture(input_address if input_address else 0)
	writer = None

	# loop over the frames from the video stream
	while True:
		# read the next frame from the file
		(grabbed, frame) = vs.read()

		# if the frame was not present it means video has ended
		if not grabbed:
			break

		# resize the frame and then detect people in that
		frame = imutils.resize(frame, width=700)
		results = detect_people(frame, net, ln,
			personIdx=LABELS.index("person"))

		# initialize the set of indexes that violate the minimum social distance
		violate = set()

		# ensure there are *at least* two people detections (required in order to compute our pairwise distance maps)
		if len(results) >= 2:
			# extract all centroids from the results and compute the Euclidean distances between all pairs of the centroids
			centroids = np.array([r[2] for r in results])
			D = dist.cdist(centroids, centroids, metric="euclidean")

			# loop over the upper triangular of the distance matrix
			for i in range(0, D.shape[0]):
				for j in range(i + 1, D.shape[1]):
					# check to see if the distance between any two centroid pairs is less than the configured number of pixels
					if D[i, j] < config.MIN_DISTANCE:
						# update our violation set with the indexes of the centroid pairs
						violate.add(i)
						violate.add(j)

		# loop over the results
		for (i, (prob, bbox, centroid)) in enumerate(results):
			# extract the bounding box and centroid coordinates, then initialize the color of the annotation
			(startX, startY, endX, endY) = bbox
			(cX, cY) = centroid
			color = (0, 255, 0)

			# if the index pair exists within the violation set, then update the color
			if i in violate:
				color = (0, 0, 255)

			# draw (1) a bounding box around the person and (2) the centroid coordinates of the person,
			cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2)
			cv2.circle(frame, (cX, cY), 5, color, 1)

		# draw the total number of social distancing violations on the output frame
		text = "Total Social Distancing Violations: {}".format(len(violate))
		cv2.putText(frame, text, (10, frame.shape[0] - 25),
			cv2.FONT_HERSHEY_SIMPLEX, 0.70, (0, 0, 255), 2)

		# check to see if the output frame should be displayed to our screen
		if display > 0:
			# display the output frame
			cv2.imshow("Frame", frame)
			key = cv2.waitKey(1) & 0xFF

			# if the `q` key was pressed, break from the loop
			if key == ord("q"):
				break

		# if an output video file path has been supplied and the video writer has not been initialized, do so now
		if output_address != "" and writer is None:
			# initialize our video writer
			fourcc = cv2.VideoWriter_fourcc(*"MJPG")
			writer = cv2.VideoWriter(output_address, fourcc, 25,
				(frame.shape[1], frame.shape[0]), True)

		# if the video writer is not None, write the frame to the output video file
		if writer is not None:
			writer.write(frame)


# Create a File Explorer label 
label_file_explorer = Label(app,  text = "Social distancing detector", width = 50, height = 5,  fg = "blue")
label_file_explorer.grid(column = 1, row = 1)

label_browse = Label(app, text = "Select Video :",bg = "WHITE",fg = "BLUE")
label_browse.grid(row=2,column=1)

browsebutton = Button(app, text="Browse", command=browsefunc)
browsebutton.grid(row = 3 , column = 1,pady = 10)

detect = Button(app, text="Render video", command=generate)
detect.grid(row = 4 , column = 1,pady = 10)

close_button = Button(app, text="EXIT",bg = "RED",fg = "WHITE",pady = 5,command = app.destroy)
close_button.grid(row = 6 , column = 1)

app.mainloop()