#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
RK3399多模态教育交互原型终端应用
主入口文件
"""

import os
import sys
import platform
import argparse
import atexit
import traceback

# 添加项目根目录到 Python 路径
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if project_root not in sys.path:
    sys.path.insert(0, project_root)

from PyQt5.QtWidgets import QApplication, QMessageBox
from PyQt5.QtCore import Qt, QTimer, QMetaObject
import time
import logging
import threading
import signal
import json
from dotenv import load_dotenv
from logging.handlers import RotatingFileHandler
from datetime import datetime

# 导入日志工具
from terminal.utils.log_utils import configure_logging, get_logger

# 解析命令行参数
def parse_args():
    parser = argparse.ArgumentParser(description='RK3399多模态教育交互原型终端应用')
    parser.add_argument('--mode', choices=['normal', 'safe', 'super-safe'], 
                      default='normal', help='运行模式: normal(正常模式), safe(安全模式), super-safe(超级安全模式)')
    parser.add_argument('--log-level', choices=['debug', 'info', 'warning', 'error'],
                      default='info', help='日志级别')
    parser.add_argument('--no-camera', action='store_true', help='禁用摄像头')
    parser.add_argument('--no-wakeword', action='store_true', help='禁用唤醒词')
    return parser.parse_args()

# 检查虚拟环境
def check_virtual_env():
    """检查是否在虚拟环境中运行"""
    in_venv = False
    venv_path = ""
    
    if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix):
        in_venv = True
        venv_path = sys.prefix
        print(f"在虚拟环境中运行: {venv_path}")
        return True, venv_path
    else:
        print("警告: 未在虚拟环境中运行！建议使用start.bat启动程序。")
        return False, ""

# 资源清理函数
def cleanup_resources():
    """清理程序资源"""
    try:
        # 获取应用控制器实例
        from terminal.application_controller import get_app_controller_instance
        app_controller = get_app_controller_instance()
        
        # 停止所有组件
        if app_controller:
            logger = get_logger(__name__)
            logger.info("正在清理资源...")
            app_controller.stop_all_components()
            logger.info("资源清理完成")
    except Exception as e:
        print(f"清理资源时出错: {e}")

# 信号处理函数
def signal_handler(sig, frame):
    """处理信号以优雅地关闭程序"""
    try:
        signal_name = signal.Signals(sig).name
        print(f"接收到信号 {signal_name}，正在优雅地关闭程序...")
    except:
        print(f"接收到信号 {sig}，正在优雅地关闭程序...")
    
    # 使用QApplication的quit方法，而不是sys.exit
    app = QApplication.instance()
    if app:
        app.quit()
    else:
        sys.exit(0)

# 异常钩子
def exception_hook(exctype, value, tb):
    """全局异常处理钩子"""
    try:
        logger = get_logger(__name__)
        logger.error("未捕获的异常", exc_info=(exctype, value, tb))
        
        # 获取应用控制器实例并清理资源
        from terminal.application_controller import get_app_controller_instance
        app_controller = get_app_controller_instance()
        if app_controller:
            app_controller.stop_all_components()
    except:
        print("处理未捕获异常时出错")
        traceback.print_exception(exctype, value, tb)
    
    # 调用原始的异常处理器
    sys.__excepthook__(exctype, value, tb)

# 主函数
def main():
    """主函数"""
    # 解析命令行参数
    args = parse_args()
    
    # 设置日志级别
    log_level = getattr(logging, args.log_level.upper(), logging.INFO)
    
    # 创建唯一的QApplication实例
    app = QApplication(sys.argv)
    
    # 检查是否在虚拟环境中运行
    in_venv, venv_path = check_virtual_env()
    if not in_venv:
        # 显示警告对话框
        msg = "程序未在虚拟环境中运行，可能导致依赖问题。\n请使用start.bat启动程序。\n是否继续？"
        result = QMessageBox.warning(None, "虚拟环境警告", msg, 
                                    QMessageBox.Yes | QMessageBox.No, 
                                    QMessageBox.No)
        if result == QMessageBox.No:
            print("程序已退出: 用户选择停止")
            return 0
    
    # 加载环境变量
    load_dotenv()
    
    # 创建日志目录
    log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "logs")
    os.makedirs(log_dir, exist_ok=True)
    
    # 配置日志系统
    root_logger = configure_logging(log_level=log_level)
    
    # 创建主模块的logger
    logger = get_logger(__name__)
    logger.info("日志系统已配置")
    
    # 注册退出时的清理函数
    atexit.register(cleanup_resources)
    
    # 注册信号处理器
    signal.signal(signal.SIGINT, signal_handler)  # Ctrl+C
    signal.signal(signal.SIGTERM, signal_handler)  # 终止信号
    
    # 在Windows上注册额外的信号处理（如果可用）
    if hasattr(signal, 'SIGBREAK'):  # Windows上的Ctrl+Break
        signal.signal(signal.SIGBREAK, signal_handler)
    
    # 注册全局异常钩子
    sys.excepthook = exception_hook
    
    try:
        # 导入UI模块
        logger.info("导入UI模块...")
        from terminal.ui.main_window import MainWindow
        
        # 导入应用控制器和初始化器
        logger.info("导入应用控制器和初始化器...")
        from terminal.application_controller import ApplicationController, get_app_controller_instance
        from terminal.app_initializer import AppInitializer
        
        # 设置应用程序属性
        app.setStyle('Fusion')  # 使用Fusion风格
        app.setAttribute(Qt.AA_UseHighDpiPixmaps)  # 启用高DPI支持
        
        # 创建主窗口
        logger.info("创建主窗口...")
        main_window = MainWindow()
        
        # 导入UI信号
        logger.info("导入UI信号...")
        from terminal.ui.signals import signals
        
        # 创建应用控制器
        logger.info("创建应用控制器...")
        app_controller = get_app_controller_instance()
        
        # 创建初始化工作线程
        logger.info("创建初始化工作线程...")
        initializer = AppInitializer(app_controller)
        
        # 连接初始化器的信号到UI信号
        initializer.initialization_progress.connect(signals.initialization_progress)
        initializer.initialization_complete.connect(signals.initialization_complete)
        
        # 连接应用控制器的信号到UI信号
        app_controller.initialized_success.connect(signals.initialization_success)
        app_controller.initialized_error.connect(signals.initialization_error)
        app_controller.module_status_update.connect(signals.module_status_update)
        
        # 连接UI信号到主窗口的槽
        signals.initialization_progress.connect(main_window.show_status_message)
        signals.initialization_complete.connect(main_window.on_initialization_complete)
        signals.initialization_success.connect(main_window.on_initialization_success)
        signals.initialization_error.connect(main_window.on_initialization_error)
        signals.module_status_update.connect(main_window.on_module_status_update)
        signals.wake_word_detected.connect(main_window.activate_window)
        
        # 注册唤醒词回调
        def on_wakeword_detected(word, confidence):
            logger.info(f"检测到唤醒词: {word}, 置信度: {confidence}")
            signals.wake_word_detected.emit(word, confidence)
        
        # 将回调函数注册到应用控制器
        app_controller.set_wakeword_callback(on_wakeword_detected)
        
        # 显示主窗口
        logger.info("显示主窗口...")
        main_window.show()
        
        # 启动初始化工作线程
        logger.info("启动初始化工作线程...")
        initializer.start()
        
        # 进入事件循环
        logger.info("进入事件循环...")
        return app.exec_()
        
    except Exception as e:
        logger.error(f"主函数执行出错: {e}")
        logger.error(traceback.format_exc())
        return 1

# 程序入口点
if __name__ == "__main__":
    sys.exit(main()) 
全程中文交流，分析问题