import time

from PIL import Image
import cv2
from utils.logger import logger, throttle
import logging
# class GetImage:
#     def __init__(self, cam_index=0, width=1920, height=1080):
#         self.cap = cv2.VideoCapture(cam_index,cv2.CAP_DSHOW)
#
#         if not self.cap.isOpened():
#             raise RuntimeError(f"无法打开摄像头 {cam_index}")
#         self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
#         self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
#         print(f"✅ 摄像头 {cam_index} 打开成功，分辨率 {width}x{height}")
#     def get_frame(self):
#         ret, im_opencv = self.cap.read()
#         im_opencv = cv2.cvtColor(im_opencv, cv2.COLOR_BGR2RGB)  # rgb 修改通道数并转换图像
#         im_opencv = im_opencv[30:30+720, 0:1280]#裁剪尺寸
#         im_PIL = Image.fromarray(im_opencv)  # 图像改成对象类型
#
#         return [im_opencv, im_PIL]
#     def release(self):
#         self.cap.release()
#         cv2.destroyAllWindows()
#         print("🔚 摄像头已释放")
#     def __del__(self):
#         # 以防忘记手动释放
#         if hasattr(self, "cap") and self.cap.isOpened():
#             self.release()
#
# get_image = GetImage()
#
# if __name__ == '__main__':
#     while True:
#         if cv2.waitKey(1) & 0xFF == ord('q'):
#             break
#         a=get_image.get_frame()
#         cv2.imshow('image',a[0])
#         print(a[0].shape)
#
#
#     cv2.destroyAllWindows()

import threading
import warnings

# 抑制OpenCV的警告信息（兼容不同版本）
import os
import sys
import io
os.environ['OPENCV_LOG_LEVEL'] = 'SILENT'
os.environ['OPENCV_IO_ENABLE_OPENEXR'] = '0'

try:
    if hasattr(cv2, 'setLogLevel'):
        if hasattr(cv2, 'LOG_LEVEL_SILENT'):
            cv2.setLogLevel(cv2.LOG_LEVEL_SILENT)
        elif hasattr(cv2, 'LOG_LEVEL_ERROR'):
            cv2.setLogLevel(cv2.LOG_LEVEL_ERROR)
        elif hasattr(cv2, 'utils'):
            cv2.utils.setLogLevel(0)
except Exception:
    pass

class GetImage:
    def __init__(self, cam_index=0, width=1920, height=1080):
        logger.info(f"🔧 正在初始化采集卡 {cam_index}...")
        self.cap = None
        self.frame = None
        self.running = True
        self.cam_index = cam_index
        
        # 尝试多种方式打开采集卡
        backends_to_try = [
            (cam_index, cv2.CAP_DSHOW),
            (cam_index, cv2.CAP_ANY),
            (cam_index, None),  # 默认后端
        ]
        
        # 重定向stderr来抑制OpenCV的错误输出
        old_stderr = sys.stderr
        suppressed_output = io.StringIO()
        
        try:
            sys.stderr = suppressed_output
            
            for idx, backend in backends_to_try:
                try:
                    with warnings.catch_warnings():
                        warnings.filterwarnings('ignore', category=UserWarning)
                        if backend is not None:
                            self.cap = cv2.VideoCapture(idx, backend)
                        else:
                            self.cap = cv2.VideoCapture(idx)
                    
                    if self.cap.isOpened():
                        # 测试读取一帧
                        ret, test_frame = self.cap.read()
                        if ret and test_frame is not None:
                            logger.info(f"✅ 采集卡 {cam_index} 打开成功")
                            break
                        else:
                            self.cap.release()
                            self.cap = None
                except Exception as e:
                    if self.cap:
                        try:
                            self.cap.release()
                        except:
                            pass
                        self.cap = None
                    continue
        finally:
            # 恢复stderr
            sys.stderr = old_stderr
        
        if self.cap is None or not self.cap.isOpened():
            logger.error(f"❌ 无法打开采集卡 {cam_index}")
            logger.error("请检查：\n  1. 采集卡是否正确连接\n  2. 采集卡索引是否正确（尝试扫描采集卡）\n  3. 采集卡驱动是否安装\n  4. 采集卡是否被其他程序占用")
            self.cap = None
            return
        
        # 设置分辨率
        try:
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
            # 实际获取设置后的分辨率
            actual_width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            actual_height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            logger.info(f"   分辨率设置: {width}x{height} -> 实际: {actual_width}x{actual_height}")
        except Exception as e:
            logger.warning(f"⚠️ 设置分辨率失败: {e}")
        
        # 启动更新线程
        threading.Thread(target=self.update, daemon=True).start()
        
        # 等待几帧确保采集卡正常工作
        import time
        time.sleep(1.0)
        logger.info(f"✅ 采集卡 {cam_index} 初始化完成")

    def update(self):
        while self.running and self.cap is not None:
            try:
                ret, frame = self.cap.read()
                if ret and frame is not None:
                    self.frame = frame
                    # 限制读取频率，避免占满CPU
                    time.sleep(0.008)
                else:
                    # 读取失败时不打印，避免刷屏
                    time.sleep(0.02)
            except Exception as e:
                # 只在异常时打印错误
                throttle(f"cap_read_err_{self.cam_index}", 2.0, logging.WARNING, f"⚠️ 采集卡 {self.cam_index} 读取异常: {e}")
                time.sleep(0.1)  # 出错时短暂延迟

    def get_frame(self):
        if self.cap is None or self.frame is None:
            return None
        try:
            im_opencv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
            im_opencv = im_opencv[30:30+720, 0:1280]
            im_PIL = Image.fromarray(im_opencv)
            return [im_opencv, im_PIL]
        except Exception as e:
            throttle(f"img_proc_err_{self.cam_index}", 2.0, logging.WARNING, f"⚠️ 图像处理错误: {e}")
            return None

    def release(self):
        self.running = False
        time.sleep(0.2)
        if self.cap is not None:
            self.cap.release()
        cv2.destroyAllWindows()

# get_image 将在main.py中初始化
get_image = None