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

class LengthConverter:
    def __init__(self, root):
        self.root = root
        self.root.title("长度单位转换器")
        self.root.geometry("700x650")
        self.root.configure(bg='#f8f9fa')
        self.root.resizable(True, True)
        
        # 设置颜色主题
        self.colors = {
            'primary': '#4a6fa5',
            'secondary': '#166088',
            'accent': '#4fc3a1',
            'bg': '#f8f9fa',
            'card_bg': '#ffffff',
            'text': '#2c3e50',
            'light_text': '#7f8c8d',
            'border': '#e0e0e0'
        }
        
        # 长度单位定义（以米为基准）
        self.length_units = {
            'km': {'name': '千米', 'full_name': '千米 (km)', 'to_meter': 1000, 'precision': 6},
            'm': {'name': '米', 'full_name': '米 (m)', 'to_meter': 1, 'precision': 3},
            'dm': {'name': '分米', 'full_name': '分米 (dm)', 'to_meter': 0.1, 'precision': 2},
            'cm': {'name': '厘米', 'full_name': '厘米 (cm)', 'to_meter': 0.01, 'precision': 1},
            'mm': {'name': '毫米', 'full_name': '毫米 (mm)', 'to_meter': 0.001, 'precision': 0},
            'μm': {'name': '微米', 'full_name': '微米 (μm)', 'to_meter': 1e-6, 'precision': 0},
            'nm': {'name': '纳米', 'full_name': '纳米 (nm)', 'to_meter': 1e-9, 'precision': 0},
            'mile': {'name': '英里', 'full_name': '英里 (mile)', 'to_meter': 1609.344, 'precision': 3},
            'yard': {'name': '码', 'full_name': '码 (yd)', 'to_meter': 0.9144, 'precision': 2},
            'foot': {'name': '英尺', 'full_name': '英尺 (ft)', 'to_meter': 0.3048, 'precision': 2},
            'inch': {'name': '英寸', 'full_name': '英寸 (in)', 'to_meter': 0.0254, 'precision': 1},
            'nautical_mile': {'name': '海里', 'full_name': '海里 (nmi)', 'to_meter': 1852, 'precision': 3},
            'li': {'name': '里', 'full_name': '里 (里)', 'to_meter': 500, 'precision': 3},
            'zhang': {'name': '丈', 'full_name': '丈 (丈)', 'to_meter': 3.333, 'precision': 3},
            'chi': {'name': '尺', 'full_name': '尺 (尺)', 'to_meter': 0.3333, 'precision': 2},
            'cun': {'name': '寸', 'full_name': '寸 (寸)', 'to_meter': 0.03333, 'precision': 2},
            'ly': {'name': '光年', 'full_name': '光年 (ly)', 'to_meter': 9.461e15, 'precision': 6}
        }
        
        # 单位分类
        self.unit_categories = {
            '公制': ['km', 'm', 'dm', 'cm', 'mm', 'μm', 'nm'],
            '英制': ['mile', 'yard', 'foot', 'inch'],
            '航海': ['nautical_mile'],
            '中国市制': ['li', 'zhang', 'chi', 'cun'],
            '天文': ['ly']
        }
        
        # 常用转换预设
        self.presets = [
            ("身高换算", "1.75", "m", ["foot", "inch"]),
            ("马拉松距离", "42.195", "km", ["mile"]),
            ("足球场长度", "105", "m", ["yard", "foot"]),
            ("手机屏幕", "6.1", "inch", ["cm", "mm"]),
            ("纸张大小(A4)", "0.297", "m", ["cm", "inch", "foot"]),
            ("长城长度", "21196.18", "km", ["mile", "li"]),
            ("珠峰高度", "8848.86", "m", ["km", "foot"]),
            ("地球直径", "12742", "km", ["mile", "li"])
        ]
        
        # 创建界面
        self.setup_ui()
        
        # 初始转换
        self.convert_length()
    
    def setup_ui(self):
        """设置用户界面"""
        # 主容器
        main_container = tk.Frame(self.root, bg=self.colors['bg'])
        main_container.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # 标题区域
        title_frame = tk.Frame(main_container, bg=self.colors['primary'], height=100)
        title_frame.pack(fill=tk.X, pady=(0, 20))
        title_frame.pack_propagate(False)
        
        title_label = tk.Label(
            title_frame,
            text="📏 长度单位转换器",
            font=('Microsoft YaHei', 24, 'bold'),
            fg='white',
            bg=self.colors['primary']
        )
        title_label.pack(expand=True)
        
        subtitle_label = tk.Label(
            title_frame,
            text="支持公制、英制、市制、天文等多种长度单位转换",
            font=('Microsoft YaHei', 10),
            fg='#e0e0e0',
            bg=self.colors['primary']
        )
        subtitle_label.pack(pady=(0, 10))
        
        # 输入区域卡片
        input_card = self.create_card(main_container, "输入")
        input_card.pack(fill=tk.X, pady=(0, 15))
        
        # 输入框
        input_frame = tk.Frame(input_card, bg=self.colors['card_bg'])
        input_frame.pack(fill=tk.X, padx=20, pady=15)
        
        tk.Label(
            input_frame,
            text="长度值:",
            font=('Microsoft YaHei', 12),
            fg=self.colors['text'],
            bg=self.colors['card_bg']
        ).pack(side=tk.LEFT, padx=(0, 10))
        
        self.length_var = tk.StringVar(value="1")
        self.length_entry = tk.Entry(
            input_frame,
            textvariable=self.length_var,
            font=('Microsoft YaHei', 14),
            width=20,
            justify='center',
            bd=2,
            relief=tk.GROOVE
        )
        self.length_entry.pack(side=tk.LEFT, padx=(0, 20))
        self.length_entry.bind('<KeyRelease>', lambda e: self.convert_length())
        
        # 从单位选择
        tk.Label(
            input_frame,
            text="从:",
            font=('Microsoft YaHei', 12),
            fg=self.colors['text'],
            bg=self.colors['card_bg']
        ).pack(side=tk.LEFT, padx=(0, 10))
        
        self.from_unit = ttk.Combobox(
            input_frame,
            values=[self.length_units[u]['full_name'] for u in self.length_units],
            state='readonly',
            width=20,
            font=('Microsoft YaHei', 12)
        )
        self.from_unit.set(self.length_units['m']['full_name'])
        self.from_unit.pack(side=tk.LEFT)
        self.from_unit.bind('<<ComboboxSelected>>', lambda e: self.convert_length())
        
        # 控制按钮
        btn_frame = tk.Frame(input_card, bg=self.colors['card_bg'])
        btn_frame.pack(fill=tk.X, padx=20, pady=(0, 15))
        
        # 转换按钮
        convert_btn = tk.Button(
            btn_frame,
            text="🔄 立即转换",
            command=self.convert_length,
            font=('Microsoft YaHei', 11, 'bold'),
            bg=self.colors['accent'],
            fg='white',
            activebackground='#3da789',
            activeforeground='white',
            bd=0,
            padx=20,
            pady=8,
            cursor='hand2'
        )
        convert_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 交换按钮
        swap_btn = tk.Button(
            btn_frame,
            text="⇄ 交换单位",
            command=self.swap_units,
            font=('Microsoft YaHei', 10),
            bg=self.colors['secondary'],
            fg='white',
            activebackground='#125d8c',
            activeforeground='white',
            bd=0,
            padx=15,
            pady=6,
            cursor='hand2'
        )
        swap_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 清空按钮
        clear_btn = tk.Button(
            btn_frame,
            text="🗑️ 清空",
            command=self.clear_all,
            font=('Microsoft YaHei', 10),
            bg='#e74c3c',
            fg='white',
            activebackground='#c0392b',
            activeforeground='white',
            bd=0,
            padx=15,
            pady=6,
            cursor='hand2'
        )
        clear_btn.pack(side=tk.LEFT)
        
        # 单位类别选择
        self.setup_unit_categories(main_container)
        
        # 结果区域
        result_frame = tk.Frame(main_container, bg=self.colors['bg'])
        result_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 15))
        
        # 左侧：转换结果
        result_card = self.create_card(result_frame, "转换结果")
        result_card.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))
        
        self.setup_results_table(result_card)
        
        # 右侧：预设和比较
        preset_card = self.create_card(result_frame, "快速预设")
        preset_card.pack(side=tk.RIGHT, fill=tk.BOTH, expand=False, padx=(10, 0))
        preset_card.configure(width=250)
        
        self.setup_presets(preset_card)
        
        # 比较区域
        compare_card = self.create_card(result_frame, "长度比较")
        compare_card.pack(side=tk.RIGHT, fill=tk.BOTH, expand=False, padx=(10, 0))
        compare_card.configure(width=250)
        
        self.setup_comparisons(compare_card)
        
        # 状态栏
        self.setup_status_bar(main_container)
    
    def create_card(self, parent, title):
        """创建卡片式容器"""
        card = tk.Frame(parent, bg=self.colors['card_bg'], relief=tk.RAISED, bd=1)
        
        # 标题
        title_label = tk.Label(
            card,
            text=title,
            font=('Microsoft YaHei', 12, 'bold'),
            fg=self.colors['primary'],
            bg=self.colors['card_bg'],
            anchor='w'
        )
        title_label.pack(fill=tk.X, padx=15, pady=10)
        
        # 分隔线
        separator = tk.Frame(card, height=1, bg=self.colors['border'])
        separator.pack(fill=tk.X, padx=10)
        
        return card
    
    def setup_unit_categories(self, parent):
        """设置单位类别选择"""
        category_card = self.create_card(parent, "单位类别筛选")
        category_card.pack(fill=tk.X, pady=(0, 15))
        
        category_frame = tk.Frame(category_card, bg=self.colors['card_bg'])
        category_frame.pack(fill=tk.X, padx=20, pady=15)
        
        self.category_vars = {}
        
        for i, (category_name, units) in enumerate(self.unit_categories.items()):
            var = tk.BooleanVar(value=True)
            self.category_vars[category_name] = var
            
            chk = tk.Checkbutton(
                category_frame,
                text=f"{category_name} ({len(units)}种)",
                variable=var,
                command=self.update_unit_list,
                font=('Microsoft YaHei', 10),
                fg=self.colors['text'],
                bg=self.colors['card_bg'],
                selectcolor=self.colors['card_bg'],
                activebackground=self.colors['card_bg'],
                cursor='hand2'
            )
            chk.grid(row=i//3, column=i%3, sticky='w', padx=10, pady=5)
    
    def setup_results_table(self, parent):
        """设置结果表格"""
        # 创建Treeview
        columns = ('unit', 'name', 'value', 'desc')
        self.results_tree = ttk.Treeview(
            parent,
            columns=columns,
            show='tree headings',
            height=12
        )
        
        # 设置列
        self.results_tree.heading('unit', text='单位', anchor='w')
        self.results_tree.heading('name', text='名称', anchor='w')
        self.results_tree.heading('value', text='数值', anchor='center')
        self.results_tree.heading('desc', text='说明', anchor='w')
        
        self.results_tree.column('unit', width=80, anchor='w')
        self.results_tree.column('name', width=100, anchor='w')
        self.results_tree.column('value', width=120, anchor='center')
        self.results_tree.column('desc', width=150, anchor='w')
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(parent, orient="vertical", command=self.results_tree.yview)
        self.results_tree.configure(yscrollcommand=scrollbar.set)
        
        # 布局
        self.results_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=15, pady=(0, 15))
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=(0, 15))
        
        # 绑定双击事件
        self.results_tree.bind('<Double-Button-1>', self.on_result_double_click)
    
    def setup_presets(self, parent):
        """设置预设按钮"""
        preset_frame = tk.Frame(parent, bg=self.colors['card_bg'])
        preset_frame.pack(fill=tk.BOTH, expand=True, padx=15, pady=15)
        
        for i, (name, value, unit, target_units) in enumerate(self.presets):
            btn_frame = tk.Frame(preset_frame, bg=self.colors['card_bg'])
            btn_frame.pack(fill=tk.X, pady=5)
            
            btn = tk.Button(
                btn_frame,
                text=name,
                command=lambda v=value, u=unit: self.apply_preset(v, u),
                font=('Microsoft YaHei', 9),
                bg='#ecf0f1',
                fg=self.colors['text'],
                bd=1,
                relief=tk.RAISED,
                padx=10,
                pady=6,
                cursor='hand2',
                anchor='w',
                justify='left'
            )
            btn.pack(side=tk.LEFT, fill=tk.X, expand=True)
            
            # 显示目标单位
            target_text = " → " + ", ".join([self.length_units[u]['name'] for u in target_units])
            tk.Label(
                btn_frame,
                text=target_text,
                font=('Microsoft YaHei', 8),
                fg=self.colors['light_text'],
                bg=self.colors['card_bg']
            ).pack(side=tk.RIGHT)
    
    def setup_comparisons(self, parent):
        """设置比较参照物"""
        compare_frame = tk.Frame(parent, bg=self.colors['card_bg'])
        compare_frame.pack(fill=tk.BOTH, expand=True, padx=15, pady=15)
        
        # 常见参照物
        comparisons = [
            ("蚂蚁长度", "0.5", "cm"),
            ("信用卡长度", "8.56", "cm"),
            ("智能手机", "15", "cm"),
            ("A4纸长度", "29.7", "cm"),
            ("成年人身高", "1.75", "m"),
            ("篮球架高度", "3.05", "m"),
            ("公交车长度", "12", "m"),
            ("足球场长度", "105", "m"),
            ("埃菲尔铁塔", "330", "m"),
            ("帝国大厦", "443", "m"),
            ("珠穆朗玛峰", "8848.86", "m"),
            ("马拉松", "42.195", "km")
        ]
        
        for name, length, unit in comparisons:
            frame = tk.Frame(compare_frame, bg=self.colors['card_bg'])
            frame.pack(fill=tk.X, pady=3)
            
            tk.Label(
                frame,
                text=name,
                font=('Microsoft YaHei', 9),
                fg=self.colors['text'],
                bg=self.colors['card_bg'],
                width=12,
                anchor='w'
            ).pack(side=tk.LEFT)
            
            tk.Label(
                frame,
                text=f"{length} {unit}",
                font=('Microsoft YaHei', 8),
                fg=self.colors['light_text'],
                bg=self.colors['card_bg']
            ).pack(side=tk.LEFT, padx=(5, 0))
            
            # 比较按钮
            compare_btn = tk.Button(
                frame,
                text="比较",
                command=lambda l=length, u=unit: self.compare_length(l, u),
                font=('Microsoft YaHei', 8),
                bg='#3498db',
                fg='white',
                bd=0,
                padx=8,
                pady=2,
                cursor='hand2'
            )
            compare_btn.pack(side=tk.RIGHT)
    
    def setup_status_bar(self, parent):
        """设置状态栏"""
        status_frame = tk.Frame(parent, bg='#2c3e50', height=30)
        status_frame.pack(fill=tk.X, side=tk.BOTTOM)
        status_frame.pack_propagate(False)
        
        self.status_var = tk.StringVar(value="就绪 | 输入长度值并选择单位进行转换")
        status_label = tk.Label(
            status_frame,
            textvariable=self.status_var,
            font=('Microsoft YaHei', 9),
            fg='white',
            bg='#2c3e50',
            anchor=tk.W,
            padx=10
        )
        status_label.pack(fill=tk.X)
    
    def update_unit_list(self):
        """更新单位列表"""
        # 获取选中的类别
        selected_categories = [cat for cat, var in self.category_vars.items() if var.get()]
        
        # 获取选中的单位
        selected_units = []
        for category in selected_categories:
            selected_units.extend(self.unit_categories[category])
        
        # 更新下拉框
        unit_list = [self.length_units[u]['full_name'] for u in selected_units if u in self.length_units]
        self.from_unit['values'] = unit_list
        
        # 如果当前单位不在列表中，设置为第一个可用单位
        current = self.from_unit.get()
        if current not in unit_list and unit_list:
            self.from_unit.set(unit_list[0])
        
        # 重新转换
        self.convert_length()
    
    def get_current_unit(self):
        """获取当前选择的单位"""
        full_name = self.from_unit.get()
        for key, unit_info in self.length_units.items():
            if unit_info['full_name'] == full_name:
                return key
        return 'm'  # 默认返回米
    
    def convert_to_meters(self, value, from_unit):
        """将任意单位转换为米"""
        if from_unit in self.length_units:
            return value * self.length_units[from_unit]['to_meter']
        return value
    
    def convert_from_meters(self, meters, to_unit):
        """将米转换为任意单位"""
        if to_unit in self.length_units and self.length_units[to_unit]['to_meter'] != 0:
            return meters / self.length_units[to_unit]['to_meter']
        return meters
    
    def format_number(self, number, precision=None):
        """格式化数字显示"""
        if number == 0:
            return "0"
        
        if abs(number) < 0.000001:  # 非常小的数
            return f"{number:.2e}"
        elif abs(number) >= 1e9:  # 非常大的数
            return f"{number:.2e}"
        elif precision is not None:
            if number.is_integer():
                return f"{int(number)}"
            return f"{number:.{precision}f}".rstrip('0').rstrip('.')
        else:
            if number.is_integer():
                return f"{int(number):,}"
            return f"{number:,.4f}".rstrip('0').rstrip('.')
    
    def get_length_description(self, value, unit_key):
        """获取长度描述"""
        unit_info = self.length_units[unit_key]
        value_in_meters = self.convert_to_meters(1, unit_key) * value
        
        if value_in_meters < 0.001:  # < 1mm
            return "极小"
        elif value_in_meters < 0.01:  # < 1cm
            return "很小"
        elif value_in_meters < 0.1:  # < 1dm
            return "小"
        elif value_in_meters < 1:  # < 1m
            return "较短"
        elif value_in_meters < 10:  # < 10m
            return "中等"
        elif value_in_meters < 100:  # < 100m
            return "较长"
        elif value_in_meters < 1000:  # < 1km
            return "长"
        elif value_in_meters < 10000:  # < 10km
            return "很长"
        else:
            return "极长"
    
    def convert_length(self, event=None):
        """执行长度转换"""
        try:
            # 获取输入
            length_str = self.length_var.get().strip()
            if not length_str:
                return
            
            try:
                length = float(length_str)
            except ValueError:
                if length_str.startswith('-') and length_str[1:].replace('.', '', 1).isdigit():
                    length = float(length_str)
                else:
                    return
            
            from_unit = self.get_current_unit()
            
            # 转换为米
            meters = self.convert_to_meters(length, from_unit)
            
            # 清空表格
            for item in self.results_tree.get_children():
                self.results_tree.delete(item)
            
            # 获取选中的单位类别
            selected_categories = [cat for cat, var in self.category_vars.items() if var.get()]
            selected_units = []
            for category in selected_categories:
                selected_units.extend(self.unit_categories[category])
            
            # 计算并显示所有选中的单位
            for unit_key in selected_units:
                if unit_key in self.length_units:
                    unit_info = self.length_units[unit_key]
                    
                    # 转换数值
                    converted_value = self.convert_from_meters(meters, unit_key)
                    
                    # 格式化显示
                    formatted_value = self.format_number(converted_value, unit_info['precision'])
                    
                    # 获取描述
                    description = self.get_length_description(converted_value, unit_key)
                    
                    # 添加到表格
                    self.results_tree.insert('', 'end', values=(
                        unit_info['full_name'].split(' ')[-1].strip('()'),
                        unit_info['name'],
                        formatted_value,
                        description
                    ))
            
            # 更新状态
            input_unit_info = self.length_units[from_unit]
            self.status_var.set(f"已转换: {length} {input_unit_info['full_name'].split(' ')[-1].strip('()')}")
            
        except Exception as e:
            self.status_var.set(f"转换错误: {str(e)}")
    
    def on_result_double_click(self, event):
        """双击结果行时设置该单位"""
        item = self.results_tree.selection()[0]
        values = self.results_tree.item(item, 'values')
        
        if values:
            unit_symbol = values[0]  # 单位符号
            
            # 查找完整的单位名称
            for unit_key, unit_info in self.length_units.items():
                if unit_info['full_name'].split(' ')[-1].strip('()') == unit_symbol:
                    self.from_unit.set(unit_info['full_name'])
                    self.convert_length()
                    break
    
    def apply_preset(self, value, unit):
        """应用预设值"""
        self.length_var.set(value)
        
        # 设置对应的单位
        if unit in self.length_units:
            self.from_unit.set(self.length_units[unit]['full_name'])
        
        self.convert_length()
        self.status_var.set(f"已应用预设: {value} {unit}")
    
    def compare_length(self, length, unit):
        """与参照物比较"""
        try:
            current_length = float(self.length_var.get())
            current_unit = self.get_current_unit()
            
            # 都转换为米进行比较
            current_meters = self.convert_to_meters(current_length, current_unit)
            compare_meters = self.convert_to_meters(float(length), unit)
            
            if compare_meters == 0:
                messagebox.showinfo("比较", "参照物长度为0，无法比较")
                return
            
            ratio = current_meters / compare_meters
            
            if ratio < 1:
                comparison = f"当前长度是参照物的 {1/ratio:.2f} 分之一"
            elif ratio > 1:
                comparison = f"当前长度是参照物的 {ratio:.2f} 倍"
            else:
                comparison = "当前长度与参照物相等"
            
            self.status_var.set(f"比较结果: {comparison}")
            
        except:
            messagebox.showwarning("错误", "请输入有效的长度值进行比较")
    
    def swap_units(self):
        """交换单位（与第一个结果单位交换）"""
        items = self.results_tree.get_children()
        if items:
            first_item = items[0]
            values = self.results_tree.item(first_item, 'values')
            
            if values:
                unit_symbol = values[0]
                
                # 查找对应的完整单位名称
                for unit_key, unit_info in self.length_units.items():
                    if unit_info['full_name'].split(' ')[-1].strip('()') == unit_symbol:
                        current_value = self.length_var.get()
                        
                        # 计算新值
                        try:
                            current_length = float(current_value)
                            current_unit = self.get_current_unit()
                            
                            meters = self.convert_to_meters(current_length, current_unit)
                            new_length = self.convert_from_meters(meters, unit_key)
                            
                            # 设置新值和单位
                            self.length_var.set(self.format_number(new_length))
                            self.from_unit.set(unit_info['full_name'])
                            
                            # 重新转换
                            self.convert_length()
                            
                        except:
                            pass
                        break
    
    def clear_all(self):
        """清空所有"""
        self.length_var.set("1")
        self.from_unit.set(self.length_units['m']['full_name'])
        
        for item in self.results_tree.get_children():
            self.results_tree.delete(item)
        
        self.status_var.set("已重置 | 输入长度值并选择单位进行转换")

def main():
    root = tk.Tk()
    
    # 设置窗口图标
    try:
        root.iconbitmap(default='icon.ico')
    except:
        pass
    
    # 设置窗口居中
    window_width = 700
    window_height = 650
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    center_x = int(screen_width/2 - window_width/2)
    center_y = int(screen_height/2 - window_height/2)
    root.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}')
    
    # 设置样式
    style = ttk.Style()
    style.theme_use('clam')
    
    # 创建应用
    app = LengthConverter(root)
    
    # 运行主循环
    root.mainloop()

if __name__ == "__main__":
    main()