import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import json
from PIL import Image, ImageTk
import math

class MathFormulaApp:
    """数学公式查询系统 - 图形界面版"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("数学公式查询系统 v2.0")
        self.root.geometry("1000x700")
        self.root.configure(bg='#f0f0f0')
        
        # 设置样式
        self.setup_styles()
        
        # 公式数据库
        self.formulas = self.init_formulas()
        
        # 创建界面
        self.create_widgets()
        
        # 绑定事件
        self.setup_bindings()
        
    def setup_styles(self):
        """设置界面样式"""
        self.colors = {
            'bg': '#f5f5f5',
            'header': '#2c3e50',
            'button': '#3498db',
            'button_hover': '#2980b9',
            'formula_bg': '#ffffff',
            'highlight': '#e8f4f8'
        }
        
        # 配置ttk样式
        style = ttk.Style()
        style.theme_use('clam')
        style.configure('TButton', padding=6, font=('微软雅黑', 10))
        style.configure('TLabel', background=self.colors['bg'], font=('微软雅黑', 10))
        style.configure('Header.TLabel', font=('微软雅黑', 16, 'bold'), foreground='white')
        style.configure('Formula.TLabel', font=('Consolas', 12), background=self.colors['formula_bg'])
        
    def init_formulas(self):
        """初始化公式数据库"""
        return {
            # 代数公式
            "quadratic": {
                "name": "一元二次方程求根公式",
                "category": "代数",
                "formula": "x = [-b ± √(b² - 4ac)] / (2a)",
                "latex": "x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}",
                "description": "求解 ax² + bx + c = 0 的根",
                "variables": {"a": "二次项系数", "b": "一次项系数", "c": "常数项"},
                "example": "解方程 2x² + 5x - 3 = 0，a=2, b=5, c=-3"
            },
            "difference_squares": {
                "name": "平方差公式",
                "category": "代数",
                "formula": "a² - b² = (a + b)(a - b)",
                "latex": "a^2 - b^2 = (a+b)(a-b)",
                "description": "两个数的平方差等于它们的和乘以差"
            },
            "perfect_square": {
                "name": "完全平方公式",
                "category": "代数",
                "formula": "(a ± b)² = a² ± 2ab + b²",
                "latex": "(a \\pm b)^2 = a^2 \\pm 2ab + b^2",
                "description": "两数和（差）的平方"
            },
            
            # 几何公式
            "circle_area": {
                "name": "圆的面积",
                "category": "几何",
                "formula": "S = πr²",
                "latex": "S = \\pi r^2",
                "description": "圆的面积计算公式",
                "variables": {"S": "面积", "r": "半径", "π": "圆周率 ≈ 3.14159"}
            },
            "circle_perimeter": {
                "name": "圆的周长",
                "category": "几何",
                "formula": "C = 2πr",
                "latex": "C = 2\\pi r",
                "description": "圆的周长计算公式"
            },
            "triangle_area": {
                "name": "三角形面积",
                "category": "几何",
                "formula": "S = (1/2) × 底 × 高",
                "latex": "S = \\frac{1}{2} \\times \\text{底} \\times \\text{高}",
                "description": "三角形面积公式"
            },
            "rectangle_area": {
                "name": "矩形面积",
                "category": "几何",
                "formula": "S = 长 × 宽",
                "latex": "S = l \\times w",
                "description": "矩形面积公式"
            },
            "pythagorean": {
                "name": "勾股定理",
                "category": "几何",
                "formula": "a² + b² = c²",
                "latex": "a^2 + b^2 = c^2",
                "description": "直角三角形中，两直角边的平方和等于斜边的平方"
            },
            
            # 三角学公式
            "sine": {
                "name": "正弦函数",
                "category": "三角学",
                "formula": "sin(θ) = 对边 / 斜边",
                "latex": "\\sin\\theta = \\frac{\\text{对边}}{\\text{斜边}}",
                "description": "直角三角形中角θ的正弦值"
            },
            "cosine": {
                "name": "余弦函数",
                "category": "三角学",
                "formula": "cos(θ) = 邻边 / 斜边",
                "latex": "\\cos\\theta = \\frac{\\text{邻边}}{\\text{斜边}}",
                "description": "直角三角形中角θ的余弦值"
            },
            "tangent": {
                "name": "正切函数",
                "category": "三角学",
                "formula": "tan(θ) = 对边 / 邻边 = sinθ / cosθ",
                "latex": "\\tan\\theta = \\frac{\\sin\\theta}{\\cos\\theta}",
                "description": "直角三角形中角θ的正切值"
            },
            "sin2θ": {
                "name": "正弦二倍角公式",
                "category": "三角学",
                "formula": "sin(2θ) = 2sinθ·cosθ",
                "latex": "\\sin(2\\theta) = 2\\sin\\theta\\cos\\theta",
                "description": "正弦二倍角公式"
            },
            
            # 微积分公式
            "derivative_power": {
                "name": "幂函数求导",
                "category": "微积分",
                "formula": "d/dx (xⁿ) = n·xⁿ⁻¹",
                "latex": "\\frac{d}{dx}x^n = nx^{n-1}",
                "description": "幂函数的导数"
            },
            "integral_power": {
                "name": "幂函数积分",
                "category": "微积分",
                "formula": "∫ xⁿ dx = xⁿ⁺¹/(n+1) + C (n ≠ -1)",
                "latex": "\\int x^n dx = \\frac{x^{n+1}}{n+1} + C",
                "description": "幂函数的不定积分"
            }
        }
    
    def create_widgets(self):
        """创建界面组件"""
        # 顶部标题栏
        header_frame = tk.Frame(self.root, bg=self.colors['header'], height=80)
        header_frame.pack(fill=tk.X)
        header_frame.pack_propagate(False)
        
        title_label = tk.Label(header_frame, text="📐 数学公式查询系统", 
                               font=('微软雅黑', 20, 'bold'), 
                               fg='white', bg=self.colors['header'])
        title_label.pack(pady=20)
        
        # 主内容区域
        main_paned = ttk.PanedWindow(self.root, orient=tk.HORIZONTAL)
        main_paned.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 左侧：搜索和列表区域
        left_frame = tk.Frame(main_paned, bg=self.colors['bg'])
        main_paned.add(left_frame, weight=1)
        
        # 搜索框
        search_frame = tk.LabelFrame(left_frame, text="🔍 搜索公式", 
                                     font=('微软雅黑', 11, 'bold'), 
                                     bg=self.colors['bg'])
        search_frame.pack(fill=tk.X, padx=5, pady=5)
        
        self.search_var = tk.StringVar()
        self.search_var.trace('w', self.on_search)
        search_entry = tk.Entry(search_frame, textvariable=self.search_var, 
                                font=('微软雅黑', 11), width=30)
        search_entry.pack(side=tk.LEFT, padx=5, pady=5, fill=tk.X, expand=True)
        
        search_btn = tk.Button(search_frame, text="搜索", command=self.search_formulas,
                              bg=self.colors['button'], fg='white', 
                              font=('微软雅黑', 10), cursor='hand2')
        search_btn.pack(side=tk.RIGHT, padx=5, pady=5)
        
        # 分类浏览
        category_frame = tk.LabelFrame(left_frame, text="📂 分类浏览", 
                                       font=('微软雅黑', 11, 'bold'),
                                       bg=self.colors['bg'])
        category_frame.pack(fill=tk.X, padx=5, pady=5)
        
        categories = ["全部"] + sorted(list(set(f['category'] for f in self.formulas.values())))
        self.category_var = tk.StringVar(value="全部")
        
        category_combo = ttk.Combobox(category_frame, textvariable=self.category_var,
                                      values=categories, state='readonly', width=25)
        category_combo.pack(padx=5, pady=5, fill=tk.X)
        category_combo.bind('<<ComboboxSelected>>', self.on_category_change)
        
        # 公式列表
        list_frame = tk.LabelFrame(left_frame, text="📋 公式列表", 
                                   font=('微软雅黑', 11, 'bold'),
                                   bg=self.colors['bg'])
        list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建带滚动条的列表框
        list_container = tk.Frame(list_frame)
        list_container.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        scrollbar = tk.Scrollbar(list_container)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        self.formula_listbox = tk.Listbox(list_container, yscrollcommand=scrollbar.set,
                                          font=('微软雅黑', 10), selectmode=tk.SINGLE,
                                          height=15)
        self.formula_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.config(command=self.formula_listbox.yview)
        
        self.formula_listbox.bind('<<ListboxSelect>>', self.on_formula_select)
        
        # 右侧：详细信息区域
        right_frame = tk.Frame(main_paned, bg=self.colors['bg'])
        main_paned.add(right_frame, weight=2)
        
        # 公式详情
        detail_frame = tk.LabelFrame(right_frame, text="📖 公式详情", 
                                     font=('微软雅黑', 11, 'bold'),
                                     bg=self.colors['bg'])
        detail_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 公式显示区域
        self.formula_display = tk.Text(detail_frame, height=8, wrap=tk.WORD,
                                       font=('Consolas', 14), bg='white')
        self.formula_display.pack(fill=tk.X, padx=10, pady=10)
        
        # 描述区域
        desc_frame = tk.LabelFrame(detail_frame, text="💡 说明", 
                                   font=('微软雅黑', 10, 'bold'),
                                   bg=self.colors['bg'])
        desc_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        self.desc_text = scrolledtext.ScrolledText(desc_frame, height=6, wrap=tk.WORD,
                                                    font=('微软雅黑', 10), bg='white')
        self.desc_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 变量说明
        var_frame = tk.LabelFrame(detail_frame, text="📊 变量说明", 
                                  font=('微软雅黑', 10, 'bold'),
                                  bg=self.colors['bg'])
        var_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        self.var_text = scrolledtext.ScrolledText(var_frame, height=4, wrap=tk.WORD,
                                                   font=('微软雅黑', 10), bg='white')
        self.var_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 计算器区域
        calc_frame = tk.LabelFrame(right_frame, text="🧮 公式计算器", 
                                   font=('微软雅黑', 11, 'bold'),
                                   bg=self.colors['bg'])
        calc_frame.pack(fill=tk.X, padx=5, pady=5)
        
        self.calc_container = tk.Frame(calc_frame, bg=self.colors['bg'])
        self.calc_container.pack(fill=tk.X, padx=10, pady=10)
        
        self.calc_label = tk.Label(self.calc_container, text="选择公式后可使用计算器", 
                                   font=('微软雅黑', 10), bg=self.colors['bg'])
        self.calc_label.pack()
        
        # 状态栏
        status_frame = tk.Frame(self.root, bg=self.colors['header'], height=30)
        status_frame.pack(fill=tk.X, side=tk.BOTTOM)
        status_frame.pack_propagate(False)
        
        self.status_label = tk.Label(status_frame, text="就绪", 
                                     font=('微软雅黑', 9), fg='white', 
                                     bg=self.colors['header'])
        self.status_label.pack(side=tk.LEFT, padx=10, pady=5)
        
        # 初始化公式列表
        self.update_formula_list()
        
    def setup_bindings(self):
        """设置事件绑定"""
        # 回车键搜索
        self.root.bind('<Return>', lambda e: self.search_formulas())
        
    def update_formula_list(self, formulas=None):
        """更新公式列表"""
        self.formula_listbox.delete(0, tk.END)
        
        if formulas is None:
            formulas = self.formulas
        
        for key, formula in formulas.items():
            display_text = f"{formula['name']} [{formula['category']}]"
            self.formula_listbox.insert(tk.END, display_text)
            # 存储公式key作为列表项的数据
            self.formula_listbox.itemconfig(tk.END, {'fg': '#333333'})
        
        # 保存公式key的映射
        self.formula_keys = list(formulas.keys())
        
        if self.formula_listbox.size() > 0:
            self.formula_listbox.selection_set(0)
            self.on_formula_select()
    
    def search_formulas(self):
        """搜索公式"""
        keyword = self.search_var.get().strip()
        
        if not keyword:
            self.update_formula_list()
            return
        
        results = {}
        for key, formula in self.formulas.items():
            if (keyword.lower() in formula['name'].lower() or 
                keyword.lower() in formula['description'].lower()):
                results[key] = formula
        
        if results:
            self.update_formula_list(results)
            self.status_label.config(text=f"找到 {len(results)} 个相关公式")
        else:
            messagebox.showinfo("提示", "未找到相关公式")
            self.update_formula_list()
    
    def on_search(self, *args):
        """实时搜索"""
        self.search_formulas()
    
    def on_category_change(self, event):
        """分类改变事件"""
        category = self.category_var.get()
        
        if category == "全部":
            self.update_formula_list()
        else:
            results = {}
            for key, formula in self.formulas.items():
                if formula['category'] == category:
                    results[key] = formula
            self.update_formula_list(results)
    
    def on_formula_select(self, event=None):
        """公式选择事件"""
        selection = self.formula_listbox.curselection()
        if not selection:
            return
        
        index = selection[0]
        if index >= len(self.formula_keys):
            return
        
        formula_key = self.formula_keys[index]
        formula = self.formulas[formula_key]
        
        # 更新显示
        self.formula_display.delete(1.0, tk.END)
        self.formula_display.insert(1.0, formula['formula'])
        self.formula_display.config(font=('Consolas', 14, 'bold'), fg='#2c3e50')
        
        self.desc_text.delete(1.0, tk.END)
        self.desc_text.insert(1.0, formula['description'])
        
        self.var_text.delete(1.0, tk.END)
        if 'variables' in formula:
            for var, desc in formula['variables'].items():
                self.var_text.insert(tk.END, f"• {var}: {desc}\n")
        else:
            self.var_text.insert(tk.END, "无变量说明")
        
        # 更新计算器界面
        self.update_calculator(formula_key)
        
        self.status_label.config(text=f"当前公式：{formula['name']}")
    
    def update_calculator(self, formula_key):
        """根据选择的公式更新计算器界面"""
        # 清除原有组件
        for widget in self.calc_container.winfo_children():
            widget.destroy()
        
        if formula_key == "quadratic":
            self.create_quadratic_calculator()
        elif formula_key == "circle_area" or formula_key == "circle_perimeter":
            self.create_circle_calculator()
        elif formula_key == "rectangle_area":
            self.create_rectangle_calculator()
        elif formula_key == "triangle_area":
            self.create_triangle_calculator()
        elif formula_key == "pythagorean":
            self.create_pythagorean_calculator()
        else:
            label = tk.Label(self.calc_container, text="该公式暂无计算器功能", 
                            font=('微软雅黑', 10), bg=self.colors['bg'])
            label.pack()
    
    def create_quadratic_calculator(self):
        """创建二次方程计算器"""
        tk.Label(self.calc_container, text="解一元二次方程 ax² + bx + c = 0", 
                font=('微软雅黑', 10, 'bold'), bg=self.colors['bg']).pack()
        
        input_frame = tk.Frame(self.calc_container, bg=self.colors['bg'])
        input_frame.pack(pady=5)
        
        tk.Label(input_frame, text="a =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.a_entry = tk.Entry(input_frame, width=8)
        self.a_entry.pack(side=tk.LEFT, padx=5)
        
        tk.Label(input_frame, text="b =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.b_entry = tk.Entry(input_frame, width=8)
        self.b_entry.pack(side=tk.LEFT, padx=5)
        
        tk.Label(input_frame, text="c =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.c_entry = tk.Entry(input_frame, width=8)
        self.c_entry.pack(side=tk.LEFT, padx=5)
        
        calc_btn = tk.Button(self.calc_container, text="计算", command=self.calc_quadratic,
                            bg=self.colors['button'], fg='white', cursor='hand2')
        calc_btn.pack(pady=5)
        
        self.quadratic_result = tk.Label(self.calc_container, text="", 
                                        font=('微软雅黑', 10), bg=self.colors['bg'], fg='green')
        self.quadratic_result.pack()
    
    def create_circle_calculator(self):
        """创建圆计算器"""
        tk.Label(self.calc_container, text="计算圆的面积和周长", 
                font=('微软雅黑', 10, 'bold'), bg=self.colors['bg']).pack()
        
        input_frame = tk.Frame(self.calc_container, bg=self.colors['bg'])
        input_frame.pack(pady=5)
        
        tk.Label(input_frame, text="半径 r =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.radius_entry = tk.Entry(input_frame, width=10)
        self.radius_entry.pack(side=tk.LEFT, padx=5)
        
        calc_btn = tk.Button(self.calc_container, text="计算", command=self.calc_circle,
                            bg=self.colors['button'], fg='white', cursor='hand2')
        calc_btn.pack(pady=5)
        
        self.circle_result = tk.Label(self.calc_container, text="", 
                                     font=('微软雅黑', 10), bg=self.colors['bg'], fg='green')
        self.circle_result.pack()
    
    def create_rectangle_calculator(self):
        """创建矩形计算器"""
        tk.Label(self.calc_container, text="计算矩形面积", 
                font=('微软雅黑', 10, 'bold'), bg=self.colors['bg']).pack()
        
        input_frame = tk.Frame(self.calc_container, bg=self.colors['bg'])
        input_frame.pack(pady=5)
        
        tk.Label(input_frame, text="长度 =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.length_entry = tk.Entry(input_frame, width=10)
        self.length_entry.pack(side=tk.LEFT, padx=5)
        
        tk.Label(input_frame, text="宽度 =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.width_entry = tk.Entry(input_frame, width=10)
        self.width_entry.pack(side=tk.LEFT, padx=5)
        
        calc_btn = tk.Button(self.calc_container, text="计算", command=self.calc_rectangle,
                            bg=self.colors['button'], fg='white', cursor='hand2')
        calc_btn.pack(pady=5)
        
        self.rect_result = tk.Label(self.calc_container, text="", 
                                   font=('微软雅黑', 10), bg=self.colors['bg'], fg='green')
        self.rect_result.pack()
    
    def create_triangle_calculator(self):
        """创建三角形计算器"""
        tk.Label(self.calc_container, text="计算三角形面积", 
                font=('微软雅黑', 10, 'bold'), bg=self.colors['bg']).pack()
        
        input_frame = tk.Frame(self.calc_container, bg=self.colors['bg'])
        input_frame.pack(pady=5)
        
        tk.Label(input_frame, text="底边长 =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.base_entry = tk.Entry(input_frame, width=10)
        self.base_entry.pack(side=tk.LEFT, padx=5)
        
        tk.Label(input_frame, text="高 =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.height_entry = tk.Entry(input_frame, width=10)
        self.height_entry.pack(side=tk.LEFT, padx=5)
        
        calc_btn = tk.Button(self.calc_container, text="计算", command=self.calc_triangle,
                            bg=self.colors['button'], fg='white', cursor='hand2')
        calc_btn.pack(pady=5)
        
        self.triangle_result = tk.Label(self.calc_container, text="", 
                                       font=('微软雅黑', 10), bg=self.colors['bg'], fg='green')
        self.triangle_result.pack()
    
    def create_pythagorean_calculator(self):
        """创建勾股定理计算器"""
        tk.Label(self.calc_container, text="计算直角三角形斜边长度", 
                font=('微软雅黑', 10, 'bold'), bg=self.colors['bg']).pack()
        
        input_frame = tk.Frame(self.calc_container, bg=self.colors['bg'])
        input_frame.pack(pady=5)
        
        tk.Label(input_frame, text="直角边 a =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.side_a_entry = tk.Entry(input_frame, width=10)
        self.side_a_entry.pack(side=tk.LEFT, padx=5)
        
        tk.Label(input_frame, text="直角边 b =", bg=self.colors['bg']).pack(side=tk.LEFT, padx=5)
        self.side_b_entry = tk.Entry(input_frame, width=10)
        self.side_b_entry.pack(side=tk.LEFT, padx=5)
        
        calc_btn = tk.Button(self.calc_container, text="计算", command=self.calc_pythagorean,
                            bg=self.colors['button'], fg='white', cursor='hand2')
        calc_btn.pack(pady=5)
        
        self.pyth_result = tk.Label(self.calc_container, text="", 
                                   font=('微软雅黑', 10), bg=self.colors['bg'], fg='green')
        self.pyth_result.pack()
    
    def calc_quadratic(self):
        """计算二次方程"""
        try:
            a = float(self.a_entry.get())
            b = float(self.b_entry.get())
            c = float(self.c_entry.get())
            
            discriminant = b**2 - 4*a*c
            
            if discriminant < 0:
                self.quadratic_result.config(text="方程无实数根", fg='red')
            elif discriminant == 0:
                x = -b / (2*a)
                self.quadratic_result.config(text=f"方程有重根：x = {x:.4f}", fg='green')
            else:
                x1 = (-b + discriminant**0.5) / (2*a)
                x2 = (-b - discriminant**0.5) / (2*a)
                self.quadratic_result.config(text=f"x₁ = {x1:.4f}, x₂ = {x2:.4f}", fg='green')
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字！")
    
    def calc_circle(self):
        """计算圆"""
        try:
            r = float(self.radius_entry.get())
            area = math.pi * r**2
            perimeter = 2 * math.pi * r
            self.circle_result.config(text=f"面积 = {area:.4f}\n周长 = {perimeter:.4f}", fg='green')
        except ValueError:
            messagebox.showerror("错误", "请输入有效的半径！")
    
    def calc_rectangle(self):
        """计算矩形"""
        try:
            length = float(self.length_entry.get())
            width = float(self.width_entry.get())
            area = length * width
            self.rect_result.config(text=f"面积 = {area:.4f}", fg='green')
        except ValueError:
            messagebox.showerror("错误", "请输入有效的长度和宽度！")
    
    def calc_triangle(self):
        """计算三角形"""
        try:
            base = float(self.base_entry.get())
            height = float(self.height_entry.get())
            area = 0.5 * base * height
            self.triangle_result.config(text=f"面积 = {area:.4f}", fg='green')
        except ValueError:
            messagebox.showerror("错误", "请输入有效的底边长和高！")
    
    def calc_pythagorean(self):
        """计算勾股定理"""
        try:
            a = float(self.side_a_entry.get())
            b = float(self.side_b_entry.get())
            c = math.sqrt(a**2 + b**2)
            self.pyth_result.config(text=f"斜边长度 = {c:.4f}", fg='green')
        except ValueError:
            messagebox.showerror("错误", "请输入有效的边长！")

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

if __name__ == "__main__":
    main()