import tkinter as tk
from tkinter import ttk, messagebox
import re

class LengthConverterGUI:
    """带图形界面的长度单位转换器"""
    
    # 定义基本单位：米(m)为标准单位
    UNITS = {
        '毫米 (mm)': 0.001,
        '厘米 (cm)': 0.01,
        '分米 (dm)': 0.1,
        '米 (m)': 1.0,
        '千米 (km)': 1000.0,
        '英寸 (in)': 0.0254,
        '英尺 (ft)': 0.3048,
        '码 (yd)': 0.9144,
        '英里 (mi)': 1609.344,
        '海里 (nmi)': 1852.0,
        '光年 (ly)': 9460730472580800.0,
        '天文单位 (au)': 149597870700.0,
        '埃 (Å)': 1e-10,
        '纳米 (nm)': 1e-9,
        '微米 (µm)': 1e-6,
    }
    
    # 单位分类
    UNIT_CATEGORIES = {
        '公制': ['毫米 (mm)', '厘米 (cm)', '分米 (dm)', '米 (m)', '千米 (km)'],
        '英制': ['英寸 (in)', '英尺 (ft)', '码 (yd)', '英里 (mi)'],
        '航海/天文': ['海里 (nmi)', '光年 (ly)', '天文单位 (au)'],
        '微观': ['埃 (Å)', '纳米 (nm)', '微米 (µm)']
    }
    
    def __init__(self, root):
        self.root = root
        self.root.title("长度单位转换器")
        self.root.geometry("700x650")
        self.root.resizable(False, False)
        
        # 设置颜色主题
        self.colors = {
            'bg': '#f0f4f8',
            'primary': '#2c3e7a',
            'secondary': '#3498db',
            'accent': '#2ecc71',
            'text': '#2c3e50',
            'light': '#ecf0f1',
            'white': '#ffffff'
        }
        
        self.root.configure(bg=self.colors['bg'])
        
        # 设置图标（如果有）
        try:
            self.root.iconbitmap(default='icon.ico')
        except:
            pass
        
        self.create_widgets()
        self.setup_bindings()
        
        # 设置默认值
        self.from_unit_combobox.current(3)  # 默认米
        self.to_unit_combobox.current(0)    # 默认毫米
        self.from_value_entry.insert(0, "1")
        self.update_result()
    
    def create_widgets(self):
        """创建所有界面组件"""
        
        # 主框架
        main_frame = tk.Frame(self.root, bg=self.colors['bg'])
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # 标题
        title_frame = tk.Frame(main_frame, bg=self.colors['bg'])
        title_frame.pack(fill=tk.X, pady=(0, 20))
        
        title_label = tk.Label(
            title_frame,
            text="📏 长度单位转换器",
            font=('Arial', 20, 'bold'),
            fg=self.colors['primary'],
            bg=self.colors['bg']
        )
        title_label.pack()
        
        subtitle_label = tk.Label(
            title_frame,
            text="支持15种长度单位，精确转换",
            font=('Arial', 10),
            fg='#7f8c8d',
            bg=self.colors['bg']
        )
        subtitle_label.pack()
        
        # 输入区域
        input_frame = tk.Frame(main_frame, bg=self.colors['white'], relief=tk.RAISED, bd=1)
        input_frame.pack(fill=tk.X, pady=(0, 15), padx=5)
        
        # 输入标签
        tk.Label(
            input_frame,
            text="输入数值:",
            font=('Arial', 11, 'bold'),
            bg=self.colors['white'],
            fg=self.colors['text']
        ).grid(row=0, column=0, padx=15, pady=(15, 10), sticky='w')
        
        # 数值输入框
        self.from_value_entry = tk.Entry(
            input_frame,
            font=('Arial', 14),
            width=20,
            relief=tk.SOLID,
            bd=1,
            highlightthickness=2,
            highlightcolor=self.colors['secondary']
        )
        self.from_value_entry.grid(row=1, column=0, padx=15, pady=(0, 15), sticky='w')
        
        # 从单位选择
        tk.Label(
            input_frame,
            text="从:",
            font=('Arial', 11, 'bold'),
            bg=self.colors['white'],
            fg=self.colors['text']
        ).grid(row=0, column=1, padx=(20, 10), pady=(15, 10), sticky='e')
        
        self.from_unit_combobox = ttk.Combobox(
            input_frame,
            values=list(self.UNITS.keys()),
            font=('Arial', 11),
            width=18,
            state='readonly'
        )
        self.from_unit_combobox.grid(row=1, column=1, padx=(20, 15), pady=(0, 15))
        
        # 转换按钮
        self.convert_button = tk.Button(
            input_frame,
            text="⇄ 转换",
            font=('Arial', 12, 'bold'),
            bg=self.colors['secondary'],
            fg='white',
            relief=tk.RAISED,
            bd=2,
            cursor='hand2',
            width=10,
            height=1,
            command=self.update_result
        )
        self.convert_button.grid(row=1, column=2, padx=15, pady=(0, 15))
        
        # 到单位选择
        tk.Label(
            input_frame,
            text="到:",
            font=('Arial', 11, 'bold'),
            bg=self.colors['white'],
            fg=self.colors['text']
        ).grid(row=0, column=3, padx=(15, 10), pady=(15, 10), sticky='e')
        
        self.to_unit_combobox = ttk.Combobox(
            input_frame,
            values=list(self.UNITS.keys()),
            font=('Arial', 11),
            width=18,
            state='readonly'
        )
        self.to_unit_combobox.grid(row=1, column=3, padx=(10, 15), pady=(0, 15))
        
        # 结果区域
        result_frame = tk.Frame(main_frame, bg=self.colors['white'], relief=tk.RAISED, bd=1)
        result_frame.pack(fill=tk.X, pady=(0, 15), padx=5)
        
        tk.Label(
            result_frame,
            text="转换结果:",
            font=('Arial', 11, 'bold'),
            bg=self.colors['white'],
            fg=self.colors['text']
        ).pack(anchor='w', padx=15, pady=(15, 10))
        
        # 结果显示框
        self.result_display = tk.Text(
            result_frame,
            height=3,
            font=('Arial', 16),
            bg=self.colors['light'],
            fg=self.colors['primary'],
            relief=tk.SUNKEN,
            bd=1,
            wrap=tk.WORD
        )
        self.result_display.pack(fill=tk.X, padx=15, pady=(0, 15))
        self.result_display.config(state=tk.DISABLED)
        
        # 快速参考区域
        quick_frame = tk.Frame(main_frame, bg=self.colors['white'], relief=tk.RAISED, bd=1)
        quick_frame.pack(fill=tk.BOTH, expand=True, padx=5)
        
        tk.Label(
            quick_frame,
            text="💡 快速参考",
            font=('Arial', 11, 'bold'),
            bg=self.colors['white'],
            fg=self.colors['text']
        ).pack(anchor='w', padx=15, pady=(15, 10))
        
        # 创建快速参考表格
        table_frame = tk.Frame(quick_frame, bg=self.colors['white'])
        table_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 15))
        
        # 表头
        headers = ['单位', '缩写', '相对米']
        for col, header in enumerate(headers):
            label = tk.Label(
                table_frame,
                text=header,
                font=('Arial', 10, 'bold'),
                bg=self.colors['primary'],
                fg='white',
                relief=tk.RAISED,
                bd=1
            )
            label.grid(row=0, column=col, sticky='nsew', padx=1, pady=1)
        
        # 数据行
        row = 1
        for unit, factor in self.UNITS.items():
            # 提取缩写
            abbr = re.search(r'\(([^)]+)\)', unit)
            abbr_text = abbr.group(1) if abbr else ''
            
            # 格式化系数
            if factor >= 1:
                factor_str = f"{factor:.2f}" if factor < 1000 else f"{factor:.2e}"
            else:
                factor_str = f"{factor:.2e}" if factor < 0.01 else f"{factor:.4f}"
            
            # 创建单元格
            tk.Label(
                table_frame,
                text=unit.replace(f' ({abbr_text})', ''),
                font=('Arial', 9),
                bg=self.colors['light'] if row % 2 == 0 else self.colors['white'],
                relief=tk.SUNKEN,
                bd=1
            ).grid(row=row, column=0, sticky='nsew', padx=1, pady=1)
            
            tk.Label(
                table_frame,
                text=abbr_text,
                font=('Arial', 9),
                bg=self.colors['light'] if row % 2 == 0 else self.colors['white'],
                relief=tk.SUNKEN,
                bd=1
            ).grid(row=row, column=1, sticky='nsew', padx=1, pady=1)
            
            tk.Label(
                table_frame,
                text=factor_str,
                font=('Arial', 9),
                bg=self.colors['light'] if row % 2 == 0 else self.colors['white'],
                relief=tk.SUNKEN,
                bd=1
            ).grid(row=row, column=2, sticky='nsew', padx=1, pady=1)
            
            row += 1
        
        # 设置列权重
        table_frame.columnconfigure(0, weight=3)
        table_frame.columnconfigure(1, weight=1)
        table_frame.columnconfigure(2, weight=2)
        
        # 底部按钮区域
        button_frame = tk.Frame(main_frame, bg=self.colors['bg'])
        button_frame.pack(fill=tk.X, pady=(10, 0))
        
        # 交换按钮
        swap_button = tk.Button(
            button_frame,
            text="↕ 交换单位",
            font=('Arial', 10),
            bg=self.colors['accent'],
            fg='white',
            relief=tk.RAISED,
            bd=2,
            cursor='hand2',
            width=12,
            command=self.swap_units
        )
        swap_button.pack(side=tk.LEFT, padx=5)
        
        # 清除按钮
        clear_button = tk.Button(
            button_frame,
            text="✕ 清除",
            font=('Arial', 10),
            bg='#e74c3c',
            fg='white',
            relief=tk.RAISED,
            bd=2,
            cursor='hand2',
            width=12,
            command=self.clear_all
        )
        clear_button.pack(side=tk.LEFT, padx=5)
        
        # 退出按钮
        exit_button = tk.Button(
            button_frame,
            text="✖ 退出",
            font=('Arial', 10),
            bg='#95a5a6',
            fg='white',
            relief=tk.RAISED,
            bd=2,
            cursor='hand2',
            width=12,
            command=self.root.quit
        )
        exit_button.pack(side=tk.RIGHT, padx=5)
        
        # 状态栏
        self.status_label = tk.Label(
            main_frame,
            text="就绪",
            font=('Arial', 9),
            fg='#7f8c8d',
            bg=self.colors['bg'],
            anchor='w'
        )
        self.status_label.pack(fill=tk.X, pady=(10, 0))
    
    def setup_bindings(self):
        """设置事件绑定"""
        self.from_value_entry.bind('<Return>', lambda e: self.update_result())
        self.from_value_entry.bind('<FocusOut>', lambda e: self.update_result())
        self.from_unit_combobox.bind('<<ComboboxSelected>>', lambda e: self.update_result())
        self.to_unit_combobox.bind('<<ComboboxSelected>>', lambda e: self.update_result())
    
    def convert(self, value, from_unit, to_unit):
        """执行单位转换"""
        # 获取转换系数
        from_factor = self.UNITS[from_unit]
        to_factor = self.UNITS[to_unit]
        
        # 转换：先转为米，再转为目标单位
        result = value * from_factor / to_factor
        return result
    
    def update_result(self):
        """更新结果显示"""
        try:
            # 获取输入值
            value_str = self.from_value_entry.get().strip()
            if not value_str:
                self.result_display.config(state=tk.NORMAL)
                self.result_display.delete(1.0, tk.END)
                self.result_display.insert(1.0, "请输入数值")
                self.result_display.config(state=tk.DISABLED)
                self.status_label.config(text="请输入数值", fg='#e74c3c')
                return
            
            value = float(value_str)
            
            # 获取单位
            from_unit = self.from_unit_combobox.get()
            to_unit = self.to_unit_combobox.get()
            
            if not from_unit or not to_unit:
                return
            
            # 执行转换
            result = self.convert(value, from_unit, to_unit)
            
            # 格式化结果显示
            from_abbr = re.search(r'\(([^)]+)\)', from_unit).group(1)
            to_abbr = re.search(r'\(([^)]+)\)', to_unit).group(1)
            
            # 智能格式化
            if abs(result) >= 1000 or (abs(result) < 0.001 and result != 0):
                result_str = f"{result:.6e}"
            elif abs(result) >= 1:
                result_str = f"{result:.6f}"
            else:
                result_str = f"{result:.6f}"
            
            # 显示结果
            self.result_display.config(state=tk.NORMAL)
            self.result_display.delete(1.0, tk.END)
            
            # 显示详细结果
            display_text = f"{value} {from_abbr} = {result_str} {to_abbr}\n"
            display_text += f"\n({value} {from_unit} = {result} {to_unit})"
            
            self.result_display.insert(1.0, display_text)
            self.result_display.config(state=tk.DISABLED)
            
            # 更新状态
            self.status_label.config(
                text=f"转换成功: {value} {from_abbr} → {result_str} {to_abbr}",
                fg=self.colors['text']
            )
            
        except ValueError:
            self.result_display.config(state=tk.NORMAL)
            self.result_display.delete(1.0, tk.END)
            self.result_display.insert(1.0, "❌ 请输入有效的数字")
            self.result_display.config(state=tk.DISABLED)
            self.status_label.config(text="错误: 无效的数值输入", fg='#e74c3c')
            
        except Exception as e:
            messagebox.showerror("错误", f"转换失败: {str(e)}")
            self.status_label.config(text=f"错误: {str(e)}", fg='#e74c3c')
    
    def swap_units(self):
        """交换源单位和目标单位"""
        from_unit = self.from_unit_combobox.get()
        to_unit = self.to_unit_combobox.get()
        
        if from_unit and to_unit:
            self.from_unit_combobox.set(to_unit)
            self.to_unit_combobox.set(from_unit)
            self.update_result()
    
    def clear_all(self):
        """清除所有输入"""
        self.from_value_entry.delete(0, tk.END)
        self.from_value_entry.insert(0, "1")
        self.from_unit_combobox.current(3)  # 默认米
        self.to_unit_combobox.current(0)    # 默认毫米
        self.result_display.config(state=tk.NORMAL)
        self.result_display.delete(1.0, tk.END)
        self.result_display.insert(1.0, "请输入数值和单位")
        self.result_display.config(state=tk.DISABLED)
        self.status_label.config(text="已重置", fg=self.colors['text'])


def main():
    """主函数"""
    root = tk.Tk()
    app = LengthConverterGUI(root)
    root.mainloop()


if __name__ == "__main__":
    main()