import sys
import cv2
import time
from PyQt5.QtCore import QThread, pyqtSignal, QObject

sys_path = sys.path[0].replace("\\", "/")
sys_path_linux = sys.path[0] + "/../.."
if sys_path_linux not in sys.path:
    sys.path.append(sys_path_linux)

from print_color import *

DEFAULT_VIDEO_SLEEP_MS = 20

# 图像处理线程
class ImageProcessingThread(QThread):
    processed_image_signal = pyqtSignal(object)

    def __init__(self):
        super().__init__()

    def run(self):
        while True:
            # 在这里添加图像处理代码
            # 这里暂时只是将图像传递给下一个线程
            time.sleep(0.01)
            self.processed_image_signal.emit(None)

# 摄像头采集线程
class CameraThread(QThread):
    image_signal = pyqtSignal(object)

    def __init__(self, camera_url, circuit_id: int = 0):
        super().__init__()

        self.camera_url = camera_url  # 摄像头url地址, 整数 或者 字符串
        self.face_detection: bool = False

        if isinstance(camera_url, int):
            self.camera_url_str = str(camera_url)
        else:
            self.camera_url_str = camera_url

        self.cap: cv2.VideoCapture = None
        self.running: bool = True

        self.fps = 0

        self.cycle_limit = DEFAULT_VIDEO_SLEEP_MS
        self.cycle_ms = 0
        self.circuit_id = circuit_id  # 摄像头对应的回路, 组合开关每一个回路都有对应的摄像头
        self.is_signal_connect = False
        self.is_emit = False

        self.set_video_cycle_ms(2000)

    def signal_connect(self, slot_func):
        self.image_signal.connect(slot_func)
        self.is_signal_connect = True

    def signal_disconnect(self):
        # 判断信号是否已连接
        if self.is_signal_connect:
            self.image_signal.disconnect()
            self.is_signal_connect = False

    def set_video_cycle_ms(self, cycle_ms: int = 10):
        if self.cycle_limit != cycle_ms:
            if cycle_ms <= DEFAULT_VIDEO_SLEEP_MS:
                self.cycle_limit = DEFAULT_VIDEO_SLEEP_MS
            else:
                self.cycle_limit = cycle_ms

    # 新建函数，改变函数延时方法
    def change_camera_url(self, camera_url: str):
        if self.circuit_id == camera_url:
            self.set_video_cycle_ms(DEFAULT_VIDEO_SLEEP_MS)
        else:
            self.set_video_cycle_ms(1000)

    def close(self):
        if self.cap == None:  # 初始化一直未完成
            self.terminate()
        self.running = False

    def run(self):
        process_count = 0
        fps_time = 0

        while self.running == True:
            inform_msg = "cameral init start, url = " + self.camera_url_str
            print_inform_msg(inform_msg)

            try:
                if isinstance(self.camera_url, int):
                    # 在 Windows 平台下，使用默认的 cv2.VideoCapture 接口
                    self.cap = cv2.VideoCapture(self.camera_url, cv2.CAP_DSHOW)
                else:
                    # 在 Linux 平台下，使用默认的 cv2.VideoCapture 接口
                    self.cap = cv2.VideoCapture(self.camera_url)

                if self.cap != None:
                    inform_msg = "cameral Init Success, url = " + self.camera_url_str
                    self.is_emit = True
                    print_inform_msg(inform_msg)
                else:
                    inform_msg = "cameral connection timeout, url = " + self.camera_url_str
                    print_inform_msg(inform_msg)

            except Exception as e:
                self.cap = None
                inform_msg = "cameral camera Init Fail, url = " + self.camera_url_str
                print_error_msg(inform_msg)

            base_time = time.time()

            while self.running and self.cap != None:
                # 延时20ms
                time.sleep(DEFAULT_VIDEO_SLEEP_MS / 1000)
                if self.cycle_ms + DEFAULT_VIDEO_SLEEP_MS < self.cycle_limit:
                    self.cycle_ms += DEFAULT_VIDEO_SLEEP_MS
                    self.cap.grab()  # 抛弃多余的帧，保持最新帧
                    continue
                else:
                    self.cycle_ms = 0

                try:
                    ret, frame = self.cap.read()
                    cur_time = time.time()

                    execution_time = cur_time - base_time
                    base_time = cur_time
                    process_count += 1

                    fps_time += execution_time

                    if fps_time >= 1:
                        self.fps = process_count
                        process_count = 0
                        fps_time = 0

                    if execution_time < 5:
                        image_object: QObject = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                        self.image_signal.emit(image_object)
                    else:  # 时间差大于5秒, 表示网络可能中断过, 退出并重新连接
                        err_message = "cameral read timeout, url = " + self.camera_url_str
                        print_error_msg(err_message)
                        break
                except Exception as e:
                    err_message = "cameral read timeout, url = " + self.camera_url_str
                    self.is_emit = False
                    print_error_msg(err_message)
                    if self.running == True:
                        time.sleep(2)
                    break

            print_inform_msg("cameral connection End")
            time.sleep(0.01)

            if self.cap != None:
                self.cap.release()
                self.cap = None

