import cv2
import mediapipe as mp
import tkinter as tk
from tkinter import filedialog

mp_drawing = mp.solutions.drawing_utils
mp_face_mesh = mp.solutions.face_mesh

# 
root = tk.Tk()
root.withdraw()  # 
video_file_path = filedialog.askopenfilename(
    title="Select existing video",
    filetypes=[("Video files", "*.mp4 *.avi ")]  # 
)

if not video_file_path:
    print("Video file was not selected.")
    exit()

# 
scale_factor = float(input("Enter the scale factor (default 1): ") or 1)

# 
cap = cv2.VideoCapture(video_file_path)

frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
fps = int(cap.get(5))

# 
user_input = input("Detailed (d) or Basic (b) analyze: ")

if user_input == 'd':
    # 
    selected_landmarks = list(range(1, 468))
else:
    # 
    selected_landmarks = [
        1, 6, 9, 14, 17, 27, 37, 40, 55, 56, 66, 82, 84, 95,
        118, 119, 131, 145, 154, 164, 165, 171, 175, 178, 183, 186,
        189, 192, 201, 202, 207, 247, 258, 259, 267, 269, 285, 296,
        310, 312, 314, 324, 346, 347, 371, 374, 381, 391, 396,
        402, 407, 410, 413, 416, 421, 422, 427, 467, 50, 187,
        205, 207, 216, 280, 411, 425, 427, 130, 359, 105, 66,
        296, 334, 63, 293
    ]

# 
#
#
with mp_face_mesh.FaceMesh(
    min_detection_confidence=0.5, min_tracking_confidence=0.5, max_num_faces=1
) as face_mesh:
    frame_count = 0

    mcr_file_count = 0
    mcr_file_lines = []

    while cap.isOpened():
        ret, frame = cap.read()

        if not ret:
            break

        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        results = face_mesh.process(frame_rgb)

        if frame_count == 0:
            # 
            with open(f"data_external_{mcr_file_count}.mcr", "w") as mcr_file:
                for i in selected_landmarks:
                    geosphere_command = f"sticker{i}=Point Box:on size:0.2\n"
                    mcr_file.write(geosphere_command)
                mcr_file.write(f"fileIn \"data_external_{mcr_file_count+1}.mcr\" \n")  # 
                #
                #

        if results.multi_face_landmarks:
            face_landmarks = results.multi_face_landmarks[0]  # 

            for i in selected_landmarks:
                landmark = face_landmarks.landmark[i]
                h, w, _ = frame.shape
                cx, cy = int(landmark.x * w), int(landmark.y * h)
                cv2.circle(frame, (cx, cy), 2, (0, 255, 0), -1)

                # 
                scaled_x = scale_factor * landmark.x * w
                scaled_y = scale_factor * landmark.y * h
                sticker_command = f"at time {frame_count} sticker{i}.pos = [ {scaled_x:.2f}, 0, {scaled_y * -1:.2f} ];\n"
                mcr_file_lines.append(sticker_command)

                if len(mcr_file_lines) >= 5000:
                    # 
                    mcr_filename = f"data_external_{mcr_file_count+1}.mcr"
                    with open(mcr_filename, "w") as mcr_file:
                        mcr_file.write("animate on\n")
                        mcr_file.write("(\n")
                        mcr_file.writelines(mcr_file_lines)
                        
                        mcr_file.write(")\n")
                        mcr_file.write(f"fileIn \"data_external_{mcr_file_count+2}.mcr\" \n")  # 
                    mcr_file_lines = []
                    mcr_file_count += 1

        #
        frame_count += 1

        cv2.imshow('Face Mesh', frame)

        if cv2.waitKey(40) & 0xFF == ord('q'):
            break

    # 
    if mcr_file_lines:
        mcr_filename = f"data_external_{mcr_file_count+1}.mcr"
        with open(mcr_filename, "w") as mcr_file:
            mcr_file.write("animate on\n")
            mcr_file.write("(\n")
            mcr_file.writelines(mcr_file_lines)
            #
            mcr_file.write(")\n")

# 
cap.release()
#

cv2.destroyAllWindows()