import os, sys, json, queue, numpy as np
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QGridLayout, QFrame, QMessageBox, QApplication, QListWidgetItem
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPixmap, QMovie

from src.config import UXUI_ASSETS, WINDOW_SIZE, BACKGROUND_COLOR, UPLOAD_DIR
from src.controllers.device_controller import DeviceController
from src.controllers.inference_controller import InferenceController
from src.controllers.media_controller import MediaController
from src.services.file_service import FileService
from src.utils.config_utils import ConfigUtils
from src.views.components.canvas_area import create_canvas_area
from src.views.components.device_list import create_device_layout
from src.views.components.toolbox import create_ai_toolbox
from src.views.components.media_panel import create_media_panel
from src.views.components.device_popup import create_device_popup, refresh_devices

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        
        # Initialize controllers
        self.device_controller = DeviceController(self)
        self.inference_controller = InferenceController(self, self.device_controller)
        self.media_controller = MediaController(self, self.inference_controller)
        
        # Initialize services
        self.file_service = FileService(self, UPLOAD_DIR)
        self.config_utils = ConfigUtils()
        
        # Set up UI and configuration
        self.destination = None
        self.current_bounding_box = None  # 儲存當前的邊界框資訊
        self.generate_global_config()
        self.init_ui()
        
    def init_ui(self):
        try:
            # Basic window setup
            self.setGeometry(100, 100, *WINDOW_SIZE)
            self.setWindowTitle('Kneron Academy AI Playground')
            self.setStyleSheet(f"background-color: {BACKGROUND_COLOR};")
            
            # Main layout
            self.layout = QVBoxLayout(self)
            self.layout.setContentsMargins(0, 0, 0, 0)
            self.setLayout(self.layout)
            
            # Show welcome screen
            self.show_welcome_label()
            
            # Switch to main page and device popup after delay
            QTimer.singleShot(500, self.show_device_popup_and_main_page)
        except Exception as e:
            print(f"Error in init_ui: {e}")
            
    def show_welcome_label(self):
        try:
            welcome_label = QLabel(self)
            logo_path = os.path.join(UXUI_ASSETS, "Assets_png/kneron_logo.png")
            print(f"Loading logo from: {logo_path}")
            
            if not os.path.exists(logo_path):
                print(f"Error: Logo file not found: {logo_path}")
                return
            
            welcome_pixmap = QPixmap(logo_path)
            if welcome_pixmap.isNull():
                print(f"Error: Unable to load image: {logo_path}")
                return
            
            welcome_label.setPixmap(welcome_pixmap)
            welcome_label.setAlignment(Qt.AlignCenter)
            self.layout.addWidget(welcome_label)
        except Exception as e:
            print(f"Error in show_welcome_label: {e}")
            
    def show_device_popup_and_main_page(self):
        try:
            # Clear welcome screen
            self.clear_layout()
            
            # 1. Initialize main page
            self.main_page = self.create_main_page()
            self.layout.addWidget(self.main_page)
            print("Main page setup complete")
            
            # 2. Set up popup and mask
            self.device_popup_mask_setup()
            print("Setting up popup mask")
            
            # 3. Refresh devices - do this after UI is fully set up
            QTimer.singleShot(100, self.device_controller.refresh_devices)
            
            self.auto_start_camera()

            # # 4. Show popup
            self.show_device_popup()
            print("Popup window setup complete")
            
            # # 5. Start camera automatically after a short delay
            # QTimer.singleShot(100, self.auto_start_camera)
        except Exception as e:
            print(f"Error in show_device_popup_and_main_page: {e}")
            
    def create_main_page(self):
        try:
            main_page = QWidget(self)
            main_layout = QHBoxLayout(main_page)
            main_page.setLayout(main_layout)

            # Left layout
            left_layout = QVBoxLayout()
            main_layout.addLayout(left_layout, 1)

            # Add Kneron logo
            logo_label = QLabel()
            logo_path = os.path.join(UXUI_ASSETS, "Assets_png/kneron_logo.png")
            logo_pixmap = QPixmap(logo_path)
            scaled_logo = logo_pixmap.scaled(104, 40, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            logo_label.setPixmap(scaled_logo)
            left_layout.addWidget(logo_label)
            
            # Add device list and AI toolbox
            self.device_frame, self.device_list_widget = create_device_layout(self, self.device_controller)
            left_layout.addWidget(self.device_frame)
            
            self.toolbox_frame = create_ai_toolbox(self, self.config_utils, self.inference_controller)
            left_layout.addWidget(self.toolbox_frame)

            # Right layout
            right_container = QWidget()
            right_layout = QGridLayout(right_container)
            right_layout.setContentsMargins(0, 0, 0, 0)
            right_layout.setSpacing(0)
            main_layout.addWidget(right_container, 2)
            
            # Add Canvas Area
            self.canvas_frame, self.canvas_label = create_canvas_area(self)
            right_layout.addWidget(self.canvas_frame, 0, 0, 1, 1)

            # Add Media Panel aligned to bottom right
            self.media_panel = create_media_panel(self, self.media_controller, self.file_service)
            right_layout.addWidget(self.media_panel, 0, 0, Qt.AlignBottom | Qt.AlignRight)

            main_layout.addWidget(right_container, 2)

            return main_page
        except Exception as e:
            print(f"Error in create_main_page: {e}")
            return QWidget(self)
            
    def device_popup_mask_setup(self):
        try:
            print("Setting up popup mask")
            # Add transparent overlay
            self.overlay = QWidget(self)
            
            # Ensure overlay is on top
            self.overlay.raise_()
            
            self.overlay.setStyleSheet("""
                background-color: rgba(0, 0, 0, 0.7);
            """)
            self.overlay.setGeometry(0, 0, self.width(), self.height())
            self.overlay_layout = QVBoxLayout(self.overlay)
            
            # Device connection popup
            self.device_popup = create_device_popup(self, self.device_controller)
            self.overlay_layout.addWidget(self.device_popup, alignment=Qt.AlignCenter)
            
            print("Popup window setup complete")
        except Exception as e:
            print(f"Error in device_popup_mask_setup: {e}")
            
    def show_device_popup(self):
        try:
            # 顯示彈窗前刷新設備列表
            # 使用新的 refresh_devices 函數，而不是直接調用 device_controller
            from src.views.components.device_popup import refresh_devices
            refresh_devices(self, self.device_controller)
            
            # 顯示彈窗
            self.overlay.show()
        except Exception as e:
            print(f"Error in show_device_popup: {e}")
            
    def hide_device_popup(self):
        try:
            self.overlay.hide()
        except Exception as e:
            print(f"Error in hide_device_popup: {e}")
            
    def clear_layout(self):
        try:
            # Clear all widgets
            while self.layout.count():
                child = self.layout.takeAt(0)
                if child.widget():
                    child.widget().deleteLater()
        except Exception as e:
            print(f"Error in clear_layout: {e}")
            
    def handle_inference_result(self, result):
        """處理來自推論工作器的結果"""
        try:
            # 輸出結果到控制台
            print("收到推論結果:", result)
            
            # 檢查結果是否包含邊界框資訊
            if isinstance(result, dict) and "bounding box" in result:
                # 更新當前邊界框資訊
                self.current_bounding_box = result["bounding box"]
                
                # 如果結果中有標籤，將其添加到邊界框中
                if "result" in result:
                    # 將標籤添加為邊界框列表的第5個元素
                    if isinstance(self.current_bounding_box, list) and len(self.current_bounding_box) >= 4:
                        # 確保邊界框列表至少有5個元素
                        while len(self.current_bounding_box) < 5:
                            self.current_bounding_box.append(None)
                        # 設置第5個元素為結果標籤
                        self.current_bounding_box[4] = result["result"]
                
                # 不需要顯示彈窗，因為邊界框會直接繪製在畫面上
                return
            
            # 對於非邊界框結果，使用彈窗顯示
            # 創建QMessageBox
            msgBox = QMessageBox(self)
            msgBox.setWindowTitle("推論結果")
            
            # 根據結果類型格式化文字
            if isinstance(result, dict):
                result_str = "\n".join(f"{key}: {value}" for key, value in result.items())
            else:
                result_str = str(result)
            
            msgBox.setText(result_str)
            msgBox.setStandardButtons(QMessageBox.Ok)
            
            # 設置樣式
            msgBox.setStyleSheet("""
                QLabel { 
                    color: white; 
                }
            """)
            
            # 顯示彈窗
            msgBox.exec_()
        except Exception as e:
            print(f"處理推論結果時發生錯誤: {e}")
            import traceback
            print(traceback.format_exc())
            
    def show_no_device_gif(self):
        """Show a GIF indicating no devices are connected"""
        try:
            no_device_label = QLabel(self)
            no_device_movie = QMovie(os.path.join(UXUI_ASSETS, "no_device_temp.gif"))
            no_device_label.setMovie(no_device_movie)
            no_device_movie.start()
            no_device_label.setAlignment(Qt.AlignCenter)
            self.layout.addWidget(no_device_label)
        except Exception as e:
            print(f"Error in show_no_device_gif: {e}")
            
    def closeEvent(self, event):
        """Handle application close event"""
        try:
            # Stop camera if running
            self.media_controller.stop_camera()
            
            # Stop inference worker
            self.inference_controller.stop_inference()
            
            # Stop recording if active
            if self.media_controller.recording:
                self.media_controller.record_video()
                
            if self.media_controller.recording_audio:
                self.media_controller.record_audio()
                
            event.accept()
        except Exception as e:
            print(f"Error during closeEvent: {e}")
            event.accept()
            
    def generate_global_config(self):
        """Generate global configuration if needed"""
        return self.config_utils.generate_global_config()
    
    def auto_start_camera(self):
        """自動啟動相機並顯示預覽"""
        print("開始啟動相機...")
        try:
            # 先清除畫布，顯示加載中的信息
            if hasattr(self, 'canvas_label'):
                self.canvas_label.setText("相機啟動中...")
                self.canvas_label.setAlignment(Qt.AlignCenter)
                self.canvas_label.setStyleSheet("color: white; font-size: 24px;")
                # 確保UI更新
                QApplication.processEvents()
                
            # 在單獨的線程中啟動相機，避免阻塞UI
            self.media_controller.start_camera()
        except Exception as e:
            print(f"啟動相機時發生錯誤: {e}")
            import traceback
            print(traceback.format_exc())