import cv2
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtGui import QImage

class VideoThread(QThread):
    change_pixmap_signal = pyqtSignal(QImage)

    def __init__(self):
        super().__init__()
        self._run_flag = True
        self._camera_open_attempts = 0
        self._max_attempts = 3

    def run(self):
        # 嘗試多次開啟相機
        while self._camera_open_attempts < self._max_attempts and self._run_flag:
            self._camera_open_attempts += 1
            print(f"嘗試開啟相機 (嘗試 {self._camera_open_attempts}/{self._max_attempts})...")
            
            # 嘗試使用DirectShow後端，通常在Windows上更快
            cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
            if not cap.isOpened():
                print("無法使用DirectShow開啟相機，嘗試預設後端")
                cap = cv2.VideoCapture(0)
                if not cap.isOpened():
                    print(f"無法使用任何後端開啟相機，等待1秒後重試...")
                    import time
                    time.sleep(1)
                    continue
            
            # 設置相機屬性以獲得更好的性能
            # 降低解析度以提高啟動速度和幀率
            cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
            cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
            cap.set(cv2.CAP_PROP_FPS, 30)
            
            # 設置緩衝區大小為1，減少延遲
            cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
            
            # 預熱相機，丟棄前幾幀以加快穩定速度
            for _ in range(5):
                cap.read()
            
            # 相機開啟成功，重置嘗試計數
            self._camera_open_attempts = 0
            
            # 主循環
            while self._run_flag:
                ret, frame = cap.read()
                if ret:
                    # 轉換為RGB格式
                    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                    height, width, channel = frame.shape
                    bytes_per_line = channel * width
                    qt_image = QImage(frame.data, width, height, bytes_per_line, QImage.Format_RGB888)
                    self.change_pixmap_signal.emit(qt_image)
                else:
                    print("無法讀取相機幀，相機可能已斷開連接")
                    break
            
            # 釋放相機資源
            cap.release()
            
            # 如果是因為停止信號而退出循環，則不再重試
            if not self._run_flag:
                break
                
            print("相機連接中斷，嘗試重新連接...")
        
        if self._camera_open_attempts >= self._max_attempts:
            print("達到最大嘗試次數，無法開啟相機")

    def stop(self):
        """停止執行緒"""
        try:
            print("正在停止相機執行緒...")
            self._run_flag = False
            # 等待執行緒完成
            if self.isRunning():
                self.wait()
            print("相機執行緒已停止")
        except Exception as e:
            print(f"停止相機執行緒時發生錯誤: {e}")
            import traceback
            print(traceback.format_exc())