import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import os
import threading
from .base_page import BasePage
from protocol import DbgUpgradeData
from protocol import DbgUpgradeResponseData
from config import Cmd

class UpgradePage(BasePage):
    def __init__(self, parent, tcp_client):

        # 升级类型映射字典
        self.upgrade_types = {
            "CMU+FPGA": 0,
            "CMU": 1,
            "FPGA": 2,
            "其他": 3
        }

        super().__init__(parent, tcp_client, "固件升级")
        
        self.upgrade_file = None
        self.upgrade_data = None
        self.current_index = 0
        self.total_packets = 0
        self.upgrading = False
        self.waiting_response = False
        

        
        tcp_client.register_callback(Cmd.UPGRADE_DATA, self.on_upgrade_response)
        
        # self.create_widgets()
    
    def create_widgets(self):
        """创建界面控件"""
        # 升级类型选择
        type_frame = ttk.Frame(self)
        type_frame.pack(fill=tk.X, padx=10, pady=5)
        
        ttk.Label(type_frame, text="升级类型:").pack(side=tk.LEFT, padx=5)
        self.upgrade_type_var = tk.StringVar(value="CMU+FPGA")  # 默认值
        
        # 创建下拉框，显示文本但存储对应的数值
        upgrade_combo = ttk.Combobox(type_frame, textvariable=self.upgrade_type_var, 
                                   values=list(self.upgrade_types.keys()), 
                                   state="readonly", width=12)
        upgrade_combo.pack(side=tk.LEFT, padx=5)
        
        # 文件选择
        file_frame = ttk.Frame(self)
        file_frame.pack(fill=tk.X, padx=10, pady=5)
        
        ttk.Label(file_frame, text="升级文件:").pack(side=tk.LEFT, padx=5)
        self.file_path_var = tk.StringVar()
        ttk.Entry(file_frame, textvariable=self.file_path_var, width=50, state='readonly').pack(side=tk.LEFT, padx=5)
        ttk.Button(file_frame, text="浏览", command=self.browse_file).pack(side=tk.LEFT, padx=5)
        
        # 进度显示
        progress_frame = ttk.Frame(self)
        progress_frame.pack(fill=tk.X, padx=10, pady=5)
        
        ttk.Label(progress_frame, text="进度:").pack(side=tk.LEFT, padx=5)
        self.progress_var = tk.DoubleVar()
        progress_bar = ttk.Progressbar(progress_frame, variable=self.progress_var, maximum=100)
        progress_bar.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        
        self.progress_label = ttk.Label(progress_frame, text="0/0")
        self.progress_label.pack(side=tk.RIGHT, padx=5)
        
        # 状态显示
        status_frame = ttk.Frame(self)
        status_frame.pack(fill=tk.X, padx=10, pady=5)
        
        ttk.Label(status_frame, text="状态:").pack(side=tk.LEFT, padx=5)
        self.status_var = tk.StringVar(value="就绪")
        ttk.Label(status_frame, textvariable=self.status_var).pack(side=tk.LEFT, padx=5)
        
        # 按钮区域
        button_frame = ttk.Frame(self)
        button_frame.pack(pady=10)
        
        self.start_button = ttk.Button(button_frame, text="开始升级", command=self.start_upgrade)
        self.start_button.pack(side=tk.LEFT, padx=5)
        
        self.stop_button = ttk.Button(button_frame, text="停止升级", command=self.stop_upgrade, state='disabled')
        self.stop_button.pack(side=tk.LEFT, padx=5)
        
        ttk.Button(button_frame, text="清除状态", command=self.clear_status).pack(side=tk.LEFT, padx=5)
    
    def get_upgrade_type_code(self):
        """获取当前选择的升级类型代码"""
        selected_text = self.upgrade_type_var.get()
        return self.upgrade_types.get(selected_text, 0)  # 默认返回0
    
    def get_upgrade_type_text(self, code=None):
        """根据代码获取升级类型文本，或获取当前选择的文本"""
        if code is not None:
            # 根据代码找文本
            for text, value in self.upgrade_types.items():
                if value == code:
                    return text
            return "其他"
        else:
            # 返回当前选择的文本
            return self.upgrade_type_var.get()
    
    def browse_file(self):
        """选择升级文件"""
        if self.upgrading:
            messagebox.showerror("错误", "升级进行中，无法选择文件")
            return
        
        file_path = filedialog.askopenfilename(
            title="选择升级文件",
            filetypes=[("二进制文件", "*.bin"), ("固件文件", "*.fw"), ("所有文件", "*.*")]
        )
        
        if file_path:
            self.file_path_var.set(file_path)
            self.upgrade_file = file_path
            file_size = os.path.getsize(file_path)
            
            upgrade_type_text = self.get_upgrade_type_text()
            self.status_var.set(f"已选择{upgrade_type_text}文件: {os.path.basename(file_path)} ({file_size} 字节)")
    
    def start_upgrade(self):
        """开始升级流程"""
        if not self.tcp_client.connected:
            messagebox.showerror("错误", "未连接到设备")
            return
        
        if not self.upgrade_file or not os.path.exists(self.upgrade_file):
            messagebox.showerror("错误", "请选择有效的升级文件")
            return
        
        # 获取升级类型代码
        upgrade_type_code = self.get_upgrade_type_code()
        upgrade_type_text = self.get_upgrade_type_text()
        
        # 读取升级文件
        try:
            with open(self.upgrade_file, 'rb') as f:
                self.upgrade_data = f.read()
        except Exception as e:
            messagebox.showerror("错误", f"读取文件失败: {e}")
            return
        
        # 计算总包数
        self.total_packets = (len(self.upgrade_data) + 1023) // 1024
        self.current_index = 0
        self.upgrading = True
        self.waiting_response = False
        
        # 更新界面状态
        self.start_button.config(state='disabled')
        self.stop_button.config(state='normal')
        self.progress_var.set(0)
        self.progress_label.config(text=f"0/{self.total_packets}")
        self.status_var.set(f"开始{upgrade_type_text}升级...")
        
        # 发送第一个数据包
        self.send_next_packet()
    
    def stop_upgrade(self):
        """停止升级"""
        if self.upgrading:
            self.upgrading = False
            self.waiting_response = False
            
            upgrade_type_text = self.get_upgrade_type_text()
            self.status_var.set(f"{upgrade_type_text}升级已停止")
            
            self.start_button.config(state='normal')
            self.stop_button.config(state='disabled')
    
    def clear_status(self):
        """清除状态"""
        if not self.upgrading:
            self.status_var.set("就绪")
            self.progress_var.set(0)
            self.progress_label.config(text="0/0")
    
    def send_next_packet(self):
        """发送下一个数据包"""
        if not self.upgrading or not self.upgrade_data or self.waiting_response:
            return
        
        if self.current_index >= self.total_packets:
            self.complete_upgrade()
            return
        
        # 计算当前数据包范围
        packet_size = 1024
        start = self.current_index * packet_size
        end = min(start + packet_size, len(self.upgrade_data))
        
        # 准备升级数据包头
        upgrade_header = DbgUpgradeData()
        upgrade_header.type = self.get_upgrade_type_code()  # 设置升级类型代码
        upgrade_header.index = self.current_index
        upgrade_header.sum = self.total_packets
        upgrade_header.len = end - start
        
        # 组合数据包头和数据
        packet_data = upgrade_header.to_bytes() + self.upgrade_data[start:end]
        
        # 发送数据包
        if self.tcp_client.send_packet(Cmd.UPGRADE_DATA, packet_data):
            self.waiting_response = True
            
            # 更新状态显示
            upgrade_type_text = self.get_upgrade_type_text()
            self.status_var.set(f"{upgrade_type_text}升级: {self.current_index + 1}/{self.total_packets}")
            
            # 更新进度
            progress = (self.current_index * packet_size) / len(self.upgrade_data) * 100
            self.progress_var.set(min(progress, 100))
            self.progress_label.config(text=f"{self.current_index}/{self.total_packets}")
        else:
            self.upgrading = False
            self.status_var.set("发送失败")
            self.start_button.config(state='normal')
            self.stop_button.config(state='disabled')
    
    def complete_upgrade(self):
        """完成升级"""
        self.upgrading = False
        self.waiting_response = False
        
        upgrade_type_text = self.get_upgrade_type_text()
        self.status_var.set(f"{upgrade_type_text}升级完成")
        self.progress_var.set(100)
        self.start_button.config(state='normal')
        self.stop_button.config(state='disabled')
        
        messagebox.showinfo("成功", f"{upgrade_type_text}升级完成")
    
    def on_upgrade_response(self, header, body):
        """处理升级响应"""
        if not self.upgrading or not self.waiting_response:
            return
        
        try:
            response = DbgUpgradeResponseData.from_bytes(body)
            
            # 检查响应是否正确
            if response.index == self.current_index:
                # 当前包发送成功，继续下一个
                self.current_index += 1
                self.waiting_response = False
                
                # 更新进度显示
                packet_size = 1024
                progress = (self.current_index * packet_size) / len(self.upgrade_data) * 100
                self.progress_var.set(min(progress, 100))
                self.progress_label.config(text=f"{self.current_index}/{self.total_packets}")
                
                # 发送下一个包或完成升级
                if self.current_index < self.total_packets:
                    upgrade_type_text = self.get_upgrade_type_text()
                    self.status_var.set(f"继续{upgrade_type_text}升级...")
                    self.send_next_packet()
                else:
                    self.complete_upgrade()
            else:
                self.status_var.set(f"响应包索引不匹配，重发")
                self.waiting_response = False
                self.send_next_packet()
                
        except Exception as e:
            self.status_var.set(f"解析响应失败: {e}")
            # 重发当前包
            self.waiting_response = False
            self.send_next_packet()