import cv2
import os
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtGui import QPixmap, QPainter, QPen, QFont, QColor
from PyQt5.QtCore import Qt, QRect

from src.models.video_thread import VideoThread
from src.utils.image_utils import qimage_to_numpy

class MediaController:
    def __init__(self, main_window, inference_controller):
        self.main_window = main_window
        self.inference_controller = inference_controller
        self.video_thread = None
        self.recording = False
        self.recording_audio = False
        self.recorded_frames = []
        self._signal_was_connected = False  # Track if signal was previously connected
        self._inference_paused = False  # 追蹤推論是否暫停
        
    def start_camera(self):
        """啟動相機進行視訊擷取"""
        try:
            if self.video_thread is None:
                print("初始化相機執行緒...")
                # 先清除畫布上的任何文字或圖像
                if hasattr(self.main_window, 'canvas_label'):
                    self.main_window.canvas_label.clear()
                
                self.video_thread = VideoThread()
                if not self._signal_was_connected:
                    try:
                        self.video_thread.change_pixmap_signal.connect(self.update_image)
                        self._signal_was_connected = True
                        print("相機信號連接成功")
                    except Exception as e:
                        print(f"連接相機信號時發生錯誤: {e}")
                
                # 啟動相機執行緒
                self.video_thread.start()
                print("相機執行緒啟動成功")
            else:
                print("相機已經在運行中")
        except Exception as e:
            print(f"啟動相機時發生錯誤: {e}")
            import traceback
            print(traceback.format_exc())
            
    def stop_camera(self):
        """停止相機"""
        try:
            if self.video_thread is not None:
                print("停止相機執行緒")
                # 確保先斷開信號連接
                if self._signal_was_connected:
                    try:
                        self.video_thread.change_pixmap_signal.disconnect()
                        self._signal_was_connected = False
                        print("已斷開相機信號連接")
                    except Exception as e:
                        print(f"斷開信號連接時發生錯誤: {e}")
                
                # 停止執行緒
                self.video_thread.stop()
                self.video_thread = None
                print("相機已完全停止")
        except Exception as e:
            print(f"停止相機時發生錯誤: {e}")
            import traceback
            print(traceback.format_exc())
            
    def update_image(self, qt_image):
        """更新圖像顯示並處理推論"""
        try:
            # 更新畫布上的圖像
            if hasattr(self.main_window, 'canvas_label'):
                pixmap = QPixmap.fromImage(qt_image)
                
                # 如果有邊界框，繪製它
                if hasattr(self.main_window, 'current_bounding_box') and self.main_window.current_bounding_box is not None:
                    painter = QPainter(pixmap)
                    pen = QPen(Qt.red)
                    pen.setWidth(2)
                    painter.setPen(pen)
                    
                    # 獲取邊界框
                    bbox_info = self.main_window.current_bounding_box
                    
                    # 檢查邊界框格式
                    if isinstance(bbox_info, dict) and "bounding box" in bbox_info:
                        # 從字典中獲取邊界框座標
                        bbox = bbox_info["bounding box"]
                        if len(bbox) >= 4:
                            # 繪製矩形
                            x1, y1, x2, y2 = bbox[0], bbox[1], bbox[2], bbox[3]
                            painter.drawRect(QRect(x1, y1, x2 - x1, y2 - y1))
                            
                            # 如果有結果標籤，繪製它
                            if "result" in bbox_info:
                                font = QFont()
                                font.setPointSize(10)
                                painter.setFont(font)
                                painter.setPen(QColor(255, 0, 0))  # 紅色
                                
                                # 計算標籤位置（邊界框上方）
                                label_x = x1
                                label_y = y1 - 10
                                
                                # 確保標籤在畫布範圍內
                                if label_y < 10:
                                    label_y = y2 + 15  # 如果上方空間不足，放在底部
                                    
                                painter.drawText(label_x, label_y, bbox_info["result"])
                    elif isinstance(bbox_info, list) and len(bbox_info) >= 4:
                        # 直接使用列表作為邊界框座標
                        x1, y1, x2, y2 = bbox_info[0], bbox_info[1], bbox_info[2], bbox_info[3]
                        painter.drawRect(QRect(x1, y1, x2 - x1, y2 - y1))
                        
                        # 如果有標籤，繪製它
                        if len(bbox_info) > 4 and bbox_info[4]:
                            font = QFont()
                            font.setPointSize(10)
                            painter.setFont(font)
                            painter.setPen(QColor(255, 0, 0))  # 紅色
                            
                            # 計算標籤位置（邊界框上方）
                            label_x = x1
                            label_y = y1 - 10
                            
                            # 確保標籤在畫布範圍內
                            if label_y < 10:
                                label_y = y2 + 15  # 如果上方空間不足，放在底部
                                
                            painter.drawText(label_x, label_y, bbox_info[4])
                    
                    painter.end()
                
                # 顯示圖像
                self.main_window.canvas_label.setPixmap(pixmap)
                
                # 只有在推論未暫停時才將影格添加到推論佇列
                if not self._inference_paused:
                    frame_np = qimage_to_numpy(qt_image)
                    self.inference_controller.add_frame_to_queue(frame_np)
                
        except Exception as e:
            print(f"更新圖像時發生錯誤: {e}")
            import traceback
            print(traceback.format_exc())
    
    def reconnect_camera_signal(self):
        """Reconnect the camera signal if it was previously disconnected"""
        if self.video_thread is not None and self._signal_was_connected:
            try:
                # Check if the signal is already connected to avoid duplicate connections
                # PyQt doesn't provide a direct way to check if a signal is connected,
                # so we use a try-except block
                try:
                    # Attempt to disconnect first to avoid multiple connections
                    self.video_thread.change_pixmap_signal.disconnect(self.update_image)
                except TypeError:
                    # Signal was not connected, which is fine
                    pass
                
                # Reconnect the signal
                self.video_thread.change_pixmap_signal.connect(self.update_image)
                print("Camera signal reconnected")
            except Exception as e:
                print(f"Error reconnecting camera signal: {e}")
                
    def record_video(self, button=None):
        """Start or stop video recording"""
        if not self.recording:
            try:
                self.recording = True
                self.recorded_frames = []
                print("Started video recording")
                
                if button:
                    button.setStyleSheet("""
                        QPushButton {
                            background: rgba(255, 0, 0, 0.3);
                            border: 1px solid red;
                            border-radius: 10px;
                        }
                    """)
            except Exception as e:
                print(f"Error starting video recording: {e}")
        else:
            try:
                self.recording = False
                print("Stopped video recording")
                
                if self.recorded_frames:
                    filename = QFileDialog.getSaveFileName(
                        self.main_window, 
                        "Save Video", 
                        "", 
                        "Video Files (*.avi)"
                    )[0]
                    
                    if filename:
                        height, width = self.recorded_frames[0].shape[:2]
                        out = cv2.VideoWriter(
                            filename, 
                            cv2.VideoWriter_fourcc(*'XVID'), 
                            20.0, 
                            (width, height)
                        )
                        
                        for frame in self.recorded_frames:
                            out.write(frame)
                        out.release()
                        print(f"Video saved to {filename}")
                
                if button:
                    button.setStyleSheet("""
                        QPushButton {
                            background: transparent;
                            border: 1px transparent;
                            border-radius: 10px;
                        }
                        QPushButton:hover {
                            background-color: rgba(255, 255, 255, 50);
                        }
                    """)
            except Exception as e:
                print(f"Error stopping video recording: {e}")
                
    def record_audio(self, button=None):
        """Start or stop audio recording"""
        if not self.recording_audio:
            try:
                self.recording_audio = True
                print("Started audio recording")
                
                if button:
                    button.setStyleSheet("""
                        QPushButton {
                            background: rgba(255, 0, 0, 0.3);
                            border: 1px solid red;
                            border-radius: 10px;
                        }
                    """)
            except Exception as e:
                print(f"Error starting audio recording: {e}")
        else:
            try:
                self.recording_audio = False
                print("Stopped audio recording")
                
                if button:
                    button.setStyleSheet("""
                        QPushButton {
                            background: transparent;
                            border: 1px transparent;
                            border-radius: 10px;
                        }
                        QPushButton:hover {
                            background-color: rgba(255, 255, 255, 50);
                        }
                    """)
            except Exception as e:
                print(f"Error stopping audio recording: {e}")
                
    def take_screenshot(self):
        """Take a screenshot of the current frame"""
        try:
            if self.main_window.canvas_label.pixmap():
                filename = QFileDialog.getSaveFileName(
                    self.main_window, 
                    "Save Screenshot", 
                    "", 
                    "Image Files (*.png *.jpg)"
                )[0]
                
                if filename:
                    self.main_window.canvas_label.pixmap().save(filename)
                    print(f"Screenshot saved to {filename}")
        except Exception as e:
            print(f"Error taking screenshot: {e}")

    def toggle_inference_pause(self):
        """切換推論暫停狀態"""
        try:
            self._inference_paused = not self._inference_paused
            if self._inference_paused:
                # 暫停時清除邊界框
                self.main_window.current_bounding_box = None
            else:
                # 恢復推論時，確保相機仍在運行
                if self.video_thread is None or not self.video_thread.isRunning():
                    self.start_camera()
            return self._inference_paused
        except Exception as e:
            print(f"切換推論暫停狀態時發生錯誤: {e}")
            import traceback
            print(traceback.format_exc())
            return self._inference_paused
        
    def is_inference_paused(self):
        """檢查推論是否暫停"""
        return self._inference_paused