"""
Multi-camera concurrent streaming stress test - threaded version.

Same as Multi_Camera_Stream_Test.py, but reads each camera on its own thread
instead of round-robining on a single thread, so cameras aren't serialized
against each other. This is closer to what real-time hand tracking (reading
every camera every frame, then sending over UDP) will actually look like.

Run standalone, no Qt/app required:
    python Multi_Camera_Stream_Test_Threaded.py
"""

import sys
import os
import time
import threading

sys.path.append(os.path.join(os.path.dirname(__file__), ".."))

from Tbd.helper import CameraObject

CAM_INDICES = [1, 2, 3, 4, 5, 6]
TEST_DURATION_SECONDS = 15
WIDTH = 1920
HEIGHT = 1080


def stream_camera(cam: CameraObject, stop_event: threading.Event, results: dict):
    successes = 0
    failures = 0

    while not stop_event.is_set():
        ok, frame = cam.capture.read()
        if ok and frame is not None:
            successes += 1
        else:
            failures += 1

    results[cam.index] = (successes, failures)


def main():
    cameras = []

    print("Opening cameras...")
    for index in CAM_INDICES:
        cam = CameraObject(capture=None, index=index)
        ok = cam.open(width=WIDTH, height=HEIGHT)
        print(f"cam{index}: {'opened' if ok else 'FAILED TO OPEN'}")
        if ok:
            cameras.append(cam)

    if not cameras:
        print("No cameras opened, aborting.")
        return

    print(f"\n{len(cameras)}/{len(CAM_INDICES)} cameras opened. Streaming (threaded) for {TEST_DURATION_SECONDS}s...\n")

    stop_event = threading.Event()
    results = {}
    threads = [
        threading.Thread(target=stream_camera, args=(cam, stop_event, results), daemon=True)
        for cam in cameras
    ]

    start = time.time()
    for t in threads:
        t.start()

    time.sleep(TEST_DURATION_SECONDS)
    stop_event.set()
    for t in threads:
        t.join()
    elapsed = time.time() - start

    print("=" * 50)
    print(f"Results after {elapsed:.1f}s:")
    for cam in cameras:
        successes, failures = results.get(cam.index, (0, 0))
        total = successes + failures
        rate = successes / total * 100 if total else 0
        fps = successes / elapsed
        print(f"cam{cam.index}: {successes} ok / {failures} failed "
              f"({rate:.1f}% success, ~{fps:.1f} fps)")
    print("=" * 50)

    for cam in cameras:
        cam.close()


if __name__ == "__main__":
    main()
