import cv2
import numpy as numpy
import time
import threading
from vcam import vcam, meshGen

clip = cv2.VideoCapture("final.avi")

fps = int(1000 / 25)


if clip.isOpened():
    print("opened")

_, first_frame = clip.read()

print(first_frame.shape[0])
print(first_frame.shape[1])
# h, w = first_frame.shape

ogw = first_frame.shape[1]  # 8000
ogh = first_frame.shape[0]  # 3950


vcam = vcam(W=ogw, H=ogh)
plane = meshGen(W=ogw, H=ogh)

plane.Z = plane.X * 0 + 1
camera_x_shift, camera_y_shift = 0, 0
camera_zoom = 1

pts3d = plane.getPlane()

# Initial region of interest as the entire image
roi = first_frame.copy()

# allocate gpu mem
frame_gpu = cv2.cuda.GpuMat()

# Window setup
window_name = "Fake Camera Controller"
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
index = int(0)
avg = float(0)
total_time = float(0)


size_multiplier = int(1)
width_final = int(1920 * size_multiplier)
height_final = int(1080 * size_multiplier)

ret, frame = clip.read()
frame_gpu = cv2.cuda.GpuMat()


# Function to process frames in a separate thread
def process_frames():
    global frame, clip, frame_gpu
    while True:
        ret, frame = clip.read()
        if not ret:
            break

        # calulate region
        roi_h, roi_w = int(ogh / camera_zoom), int(ogw / camera_zoom)
        x1 = min(max(0, ogw // 2 - roi_w // 2 + camera_x_shift), ogw - roi_w)
        y1 = min(max(0, ogh // 2 - roi_h // 2 + camera_y_shift), ogh - roi_h)
        x2, y2 = x1 + roi_w, y1 + roi_h

        # Directly manipulate the frame in-place
        frame = frame[y1:y2, x1:x2]
        frame_gpu.upload(frame)
        frame_gpu = cv2.cuda.resize(
            frame_gpu, (width_final, height_final), interpolation=cv2.INTER_LINEAR
        )
        frame = frame_gpu.download()

    clip.release()


# Create a thread for frame processing
frame_processing_thread = threading.Thread(target=process_frames)
frame_processing_thread.start()

while True:
    time_start = time.time()
    if frame.shape[0] <= 0:
        break
    cv2.imshow("test", frame)

    key = cv2.waitKey(fps)

    # ... (rest of your code for user input handling remains the same)

    time_end = time.time()
    total_time_frame = time_end - time_start
    print(total_time_frame)
    total_time += total_time_frame
    key = cv2.waitKey(fps)

    # Exit loop on pressing 'ESC' key
    # Zoom controls
    if key == ord("+") or key == ord("="):
        camera_zoom *= 1.1
    elif key == ord("-"):
        camera_zoom /= 1.1
        # Pan controls
    elif key == ord("w"):
        camera_y_shift -= int(ogh * 0.01)
    elif key == ord("s"):
        camera_y_shift += int(ogh * 0.01)
    elif key == ord("a"):
        camera_x_shift -= int(ogw * 0.01)
    elif key == ord("d"):
        camera_x_shift += int(ogw * 0.01)
    elif key == 27:
        break

    index += 1
    time_end = time.time()
    total_time_frame = time_end - time_start
    print(total_time_frame)
    total_time += total_time_frame


avg = total_time / index  #

# print(f"resolution {width_final} x {height_final}")
# print(f"average frame time: {avg}")
# print(f"total_time: {total_time}")
# clip.release()
# cv2.destroyAllWindows()

# Wait for the frame processing thread to finish
frame_processing_thread.join()
