"""
Goal: Detect MAJOR UI changes (new page, app switch, modal, etc.)
      in < 10 ms per frame, 1ms stretch goal.

Ignore:
  • Mouse cursor movement
  • Clock / battery / Wi-Fi icons updating

Input: numpy arrays (BGR, uint8) - already decoded from PNG
Output: bool

Good if:
  • Correct on all 3 test pairs below
  • Average runtime < 10 ms

I recommend using UV for this project.

https://docs.astral.sh/uv/getting-started/installation/

```
curl -LsSf https://astral.sh/uv/install.sh | sh
```

Then restart your terminal and run the script:

```
uv run main.py
```
"""

import time
import numpy as np
import cv2
from typing import List, Tuple

def is_major_change(prev: np.ndarray, curr: np.ndarray) -> bool:
    """
    Return True if the two screenshots represent meaningfully different UI state.
    
    Args:
        prev: Previous frame as numpy array (H, W, 3) BGR uint8
        curr: Current frame as numpy array (H, W, 3) BGR uint8
    
    Returns:
        True if major UI change detected, False otherwise
    """
    # --- your code here ------------------------------------------------
    raise NotImplementedError
    # ------------------------------------------------------------------


TEST_PAIRS = [
    # 1. Same webpage, only cursor moved, clock + a few pixels animated: False
    ("test_same_page_cursor_moved/frame_001.png", "test_same_page_cursor_moved/frame_002.png", False),

    # 2. Browser switched pages: True
    ("test_app_switch/frame_001.png", "test_app_switch/frame_002.png", True),

    # 3. Slack opened Settings modal: True
    ("test_modal/frame_001.png", "test_modal/frame_002.png", True),
]


def load_image(path: str) -> np.ndarray:
    """Load image as BGR numpy array."""
    img = cv2.imread(path)
    if img is None:
        raise FileNotFoundError(f"Could not load image: {path}")
    return img


def run_tests():
    total_time = 0.0
    results: List[str] = []

    loaded_pairs: List[Tuple[np.ndarray, np.ndarray, bool, str, str]] = []
    for prev_path, curr_path, expected in TEST_PAIRS:
        prev = load_image(prev_path)
        curr = load_image(curr_path)
        loaded_pairs.append((prev, curr, expected, prev_path, curr_path))
        print(f"Loaded: {prev_path} ({prev.shape}) and {curr_path} ({curr.shape})")
    
    print("\n" + "="*70 + "\n")

    for prev, curr, expected, prev_path, curr_path in loaded_pairs:
        start = time.perf_counter()
        result = is_major_change(prev, curr)
        elapsed_ms = (time.perf_counter() - start) * 1000
        total_time += elapsed_ms

        ok = "PASSED" if result == expected else "FAILED"
        folder = prev_path.split("/")[0]
        results.append(f"{ok} {folder:>30} | {elapsed_ms:5.2f} ms "
                       f"| expected {expected} got {result}")

    avg_ms = total_time / len(TEST_PAIRS)
    print("\n".join(results))
    print(f"\nAverage time per frame: {avg_ms:.2f} ms")


if __name__ == "__main__":
    run_tests()
