from typing import Callable

import cv2
import numpy as np
from PIL import Image
from tqdm import tqdm, trange


def compare(frame1, frame2):
    absdiff = cv2.absdiff(frame1, frame2)
    return np.mean(absdiff)


def load_frames(cap: cv2.VideoCapture, frame_interval: int, progress: Callable) -> list:
    frames = []
    num_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    i = 0
    res = cap.grab()
    while i < num_frames:
        if res:
            frames.append(cap.retrieve()[1])
        for _ in range(frame_interval):
            res = cap.grab()
        i += frame_interval
        progress(i)

    return frames


def differences(frames: list, progress: Callable) -> list[float]:
    diffs = []

    for index, (frame1, frame2) in enumerate(zip(frames[:-1], frames[1:]), start=1):
        diff = compare(frame1, frame2)
        diffs.append(diff)
        progress(index)

    return diffs


def select_frames(frames: list, diffs: list, threshold: float) -> list[Image.Image]:
    selected_frames = [frames[0]]

    for frame, diff in zip(frames[1:], diffs, strict=True):
        if diff > threshold:
            selected_frames.append(frame)

    # Convert to Images
    return [Image.fromarray(frame[:, :, ::-1]) for frame in selected_frames]
