import cv2
import pytesseract

# If needed, set your Tesseract path manually:
# pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

BACKEND = cv2.CAP_MSMF

TEST_RESOLUTIONS = [
    (3840, 2160),
    (2560, 1440),
    (1920, 1080),
    (1280, 720),
    (640, 480)
]

# -------------------------------
# CAMERA SCANNING
# -------------------------------

def get_connected_cameras(max_index=10):
    found = []
    for index in range(max_index):
        cap = cv2.VideoCapture(index, BACKEND)
        if cap.isOpened():
            found.append(index)
        cap.release()
    return found

def test_camera_resolution(cam_index):
    cap = cv2.VideoCapture(cam_index, BACKEND)
    best_res = (0, 0)

    for width, height in TEST_RESOLUTIONS:
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)

        ret, frame = cap.read()
        if ret:
            h, w = frame.shape[:2]
            if w == width and h == height:
                best_res = (width, height)
                break

    cap.release()
    return best_res

# -------------------------------
# OCR REGION SELECTION
# -------------------------------

selecting = False
ix, iy = -1, -1
rx, ry, rw, rh = 0, 0, 0, 0

def mouse_callback(event, x, y, flags, param):
    global selecting, ix, iy, rx, ry, rw, rh

    if event == cv2.EVENT_LBUTTONDOWN:
        selecting = True
        ix, iy = x, y

    elif event == cv2.EVENT_MOUSEMOVE and selecting:
        rx, ry = min(ix, x), min(iy, y)
        rw, rh = abs(ix - x), abs(iy - y)

    elif event == cv2.EVENT_LBUTTONUP:
        selecting = False
        rx, ry = min(ix, x), min(iy, y)
        rw, rh = abs(ix - x), abs(iy - y)

# -------------------------------
# MAIN CAMERA + OCR LOOP
# -------------------------------

def open_camera_with_ocr(cam_index, resolution):
    width, height = resolution
    cap = cv2.VideoCapture(cam_index, BACKEND)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)

    cv2.namedWindow("Camera")
    cv2.setMouseCallback("Camera", mouse_callback)

    last_text = ""

    print("\n🟦 Drag a box on the video feed to select OCR region.")
    print("🟩 OCR will print to console when text changes.")
    print("Press 'q' to quit.\n")

    while True:
        ret, frame = cap.read()
        if not ret:
            print("❌ Failed to read frame.")
            break

        # Draw selection rectangle
        if rw > 0 and rh > 0:
            cv2.rectangle(frame, (rx, ry), (rx + rw, ry + rh), (0, 255, 0), 2)

            roi = frame[ry:ry+rh, rx:rx+rw]

            # OCR only when region is valid
            if roi.size > 0:
                text = pytesseract.image_to_string(roi).strip()

                if text and text != last_text:
                    print("\n----------------------------")
                    print("📘 OCR TEXT UPDATED:")
                    print(text)
                    print("----------------------------")
                    last_text = text

        cv2.imshow("Camera", frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()

# -------------------------------
# MAIN
# -------------------------------

def main():
    print("🔍 Scanning for cameras...\n")

    cameras = get_connected_cameras()
    if not cameras:
        print("❌ No cameras detected.")
        return

    best_cam = None
    best_res = (0, 0)

    for cam in cameras:
        print(f"Testing camera {cam}...")
        res = test_camera_resolution(cam)
        print(f"  Supported: {res}")

        if res > best_res:
            best_res = res
            best_cam = cam

    if best_cam is None:
        print("❌ No usable camera found.")
        return

    print(f"\n🏆 Highest resolution camera: {best_cam} at {best_res}")
    open_camera_with_ocr(best_cam, best_res)


if __name__ == "__main__":
    main()