import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import json
import os


class FormulaSearchApp:
    def __init__(self, root):
        self.root = root
        self.root.title("数学公式查询系统")
        self.root.geometry("800x600")

        # 公式数据库
        self.formulas = {
            "代数": {
                "二次方程求根公式": r"x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}",
                "平方差公式": r"a^2 - b^2 = (a+b)(a-b)",
                "完全平方公式": r"(a \pm b)^2 = a^2 \pm 2ab + b^2",
                "立方和公式": r"a^3 + b^3 = (a+b)(a^2 - ab + b^2)",
                "韦达定理": r"x_1 + x_2 = -\frac{b}{a},\quad x_1x_2 = \frac{c}{a}"
            },
            "几何": {
                "勾股定理": r"a^2 + b^2 = c^2",
                "圆的面积": r"S = \pi r^2",
                "圆的周长": r"C = 2\pi r",
                "三角形面积": r"S = \frac{1}{2}bh",
                "球体体积": r"V = \frac{4}{3}\pi r^3"
            },
            "微积分": {
                "导数定义": r"f'(x) = \lim_{h \to 0} \frac{f(x+h)-f(x)}{h}",
                "积分基本定理": r"\int_a^b f(x)dx = F(b) - F(a)",
                "常见导数": r"\frac{d}{dx} x^n = nx^{n-1}",
                "常见积分": r"\int x^n dx = \frac{x^{n+1}}{n+1} + C"
            },
            "三角函数": {
                "正弦定理": r"\frac{a}{\sin A} = \frac{b}{\sin B} = \frac{c}{\sin C} = 2R",
                "余弦定理": r"c^2 = a^2 + b^2 - 2ab\cos C",
                "和角公式": r"\sin(A+B) = \sin A\cos B + \cos A\sin B",
                "倍角公式": r"\sin 2\theta = 2\sin\theta\cos\theta"
            }
        }

        # 存储公式列表数据
        self.formula_data = []

        self.setup_ui()

    def setup_ui(self):
        # 顶部标题
        title_label = tk.Label(self.root, text="数学公式查询系统",
                               font=("Arial", 20, "bold"))
        title_label.pack(pady=10)

        # 搜索框架
        search_frame = tk.Frame(self.root)
        search_frame.pack(pady=10, padx=20, fill=tk.X)

        tk.Label(search_frame, text="搜索公式:", font=(
            "Arial", 12)).pack(side=tk.LEFT)

        self.search_var = tk.StringVar()
        self.search_var.trace("w", lambda *args: self.on_search_change())
        search_entry = tk.Entry(search_frame, textvariable=self.search_var,
                                font=("Arial", 12), width=40)
        search_entry.pack(side=tk.LEFT, padx=10)

        # 分类选择
        tk.Label(search_frame, text="  分类:", font=(
            "Arial", 12)).pack(side=tk.LEFT)

        self.category_var = tk.StringVar(value="全部")
        categories = ["全部"] + list(self.formulas.keys())
        category_combo = ttk.Combobox(search_frame, textvariable=self.category_var,
                                      values=categories, state="readonly", width=15)
        category_combo.pack(side=tk.LEFT, padx=5)
        category_combo.bind("<<ComboboxSelected>>",
                            lambda e: self.on_category_change())

        # 主内容区域
        main_frame = tk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)

        # 左侧公式列表
        list_frame = tk.LabelFrame(main_frame, text="公式列表", font=("Arial", 12))
        list_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))

        self.formula_listbox = tk.Listbox(list_frame, font=("Arial", 12),
                                          selectbackground="#4CAF50", selectforeground="white")
        self.formula_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        self.formula_listbox.bind("<<ListboxSelect>>", self.on_formula_select)

        # 添加滚动条
        scrollbar = tk.Scrollbar(list_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.formula_listbox.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.formula_listbox.yview)

        # 右侧显示区域
        display_frame = tk.LabelFrame(
            main_frame, text="公式详情", font=("Arial", 12))
        display_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        # 公式名称
        self.formula_name_label = tk.Label(display_frame, text="",
                                           font=("Arial", 16, "bold"))
        self.formula_name_label.pack(pady=10)

        # 公式显示区域
        formula_display = tk.Frame(
            display_frame, bg="white", relief=tk.SUNKEN, bd=2)
        formula_display.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        self.formula_text = scrolledtext.ScrolledText(formula_display,
                                                      font=("Courier New", 18),
                                                      height=6, wrap=tk.WORD)
        self.formula_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 分类标签
        tk.Label(display_frame, text="分类:", font=(
            "Arial", 12)).pack(anchor=tk.W, padx=10)
        self.category_label = tk.Label(display_frame, text="", font=("Arial", 12, "bold"),
                                       fg="blue")
        self.category_label.pack(anchor=tk.W, padx=10)

        # 描述区域
        tk.Label(display_frame, text="描述/用途:", font=("Arial", 12)
                 ).pack(anchor=tk.W, padx=10, pady=(10, 0))
        self.description_text = scrolledtext.ScrolledText(display_frame,
                                                          font=("Arial", 12),
                                                          height=4, wrap=tk.WORD)
        self.description_text.pack(fill=tk.X, padx=10, pady=5)

        # 底部按钮
        button_frame = tk.Frame(self.root)
        button_frame.pack(pady=10)

        tk.Button(button_frame, text="添加新公式", command=self.add_formula,
                  font=("Arial", 12), bg="#2196F3", fg="white").pack(side=tk.LEFT, padx=5)

        tk.Button(button_frame, text="导出公式", command=self.export_formulas,
                  font=("Arial", 12), bg="#4CAF50", fg="white").pack(side=tk.LEFT, padx=5)

        tk.Button(button_frame, text="导入公式", command=self.import_formulas,
                  font=("Arial", 12), bg="#FF9800", fg="white").pack(side=tk.LEFT, padx=5)

        tk.Button(button_frame, text="退出", command=self.root.quit,
                  font=("Arial", 12), bg="#f44336", fg="white").pack(side=tk.LEFT, padx=5)

        # 初始化显示
        self.update_formula_list()

    def update_formula_list(self, search_text=None, category=None):
        if search_text is None:
            search_text = self.search_var.get()
        if category is None:
            category = self.category_var.get()

        self.formula_listbox.delete(0, tk.END)
        self.formula_data = []

        search_lower = search_text.lower()

        for cat, formulas in self.formulas.items():
            if category != "全部" and cat != category:
                continue

            for name, formula in formulas.items():
                if search_lower in name.lower():
                    self.formula_data.append((cat, name, formula))
                    display_text = f"[{cat}] {name}"
                    self.formula_listbox.insert(tk.END, display_text)

    def on_search_change(self):
        search_text = self.search_var.get()
        category = self.category_var.get()
        self.update_formula_list(search_text, category)

    def on_category_change(self):
        search_text = self.search_var.get()
        category = self.category_var.get()
        self.update_formula_list(search_text, category)

    def on_formula_select(self, event):
        selection = self.formula_listbox.curselection()
        if not selection:
            return

        index = selection[0]
        if index < len(self.formula_data):
            cat, name, formula = self.formula_data[index]

            # 更新显示
            self.formula_name_label.config(text=name)
            self.category_label.config(text=cat)

            # 清空并插入公式
            self.formula_text.delete(1.0, tk.END)
            self.formula_text.insert(tk.END, formula)

            # 更新描述
            self.description_text.delete(1.0, tk.END)
            descriptions = {
                "二次方程求根公式": "用于求解一元二次方程 ax²+bx+c=0 的根",
                "勾股定理": "直角三角形两直角边的平方和等于斜边的平方",
                "导数定义": "函数在某一点处的瞬时变化率",
                "正弦定理": "三角形边长与其对应角的正弦值之比等于外接圆直径"
            }
            description = descriptions.get(name, f"这是{cat}领域的重要公式")
            self.description_text.insert(tk.END, description)

    def add_formula(self):
        # 创建添加公式的对话框
        add_window = tk.Toplevel(self.root)
        add_window.title("添加新公式")
        add_window.geometry("500x400")

        tk.Label(add_window, text="分类:", font=("Arial", 12)).grid(
            row=0, column=0, padx=10, pady=10, sticky=tk.W)
        new_category_var = tk.StringVar()
        category_combo = ttk.Combobox(add_window, textvariable=new_category_var,
                                      values=list(self.formulas.keys()) + ["新分类"], width=20)
        category_combo.grid(row=0, column=1, pady=10, sticky=tk.W)

        tk.Label(add_window, text="新分类名:", font=("Arial", 12)).grid(
            row=1, column=0, padx=10, pady=5, sticky=tk.W)
        new_cat_name_var = tk.StringVar()
        tk.Entry(add_window, textvariable=new_cat_name_var, width=20).grid(
            row=1, column=1, pady=5, sticky=tk.W)

        tk.Label(add_window, text="公式名称:", font=("Arial", 12)).grid(
            row=2, column=0, padx=10, pady=10, sticky=tk.W)
        name_var = tk.StringVar()
        tk.Entry(add_window, textvariable=name_var, width=30).grid(
            row=2, column=1, pady=10, sticky=tk.W)

        tk.Label(add_window, text="公式内容 (LaTeX格式):", font=("Arial", 12)).grid(
            row=3, column=0, padx=10, pady=5, sticky=tk.NW)
        formula_text = scrolledtext.ScrolledText(
            add_window, height=8, width=40)
        formula_text.grid(row=3, column=1, pady=5, sticky=tk.W)

        tk.Label(add_window, text="描述:", font=("Arial", 12)).grid(
            row=4, column=0, padx=10, pady=5, sticky=tk.NW)
        desc_text = scrolledtext.ScrolledText(add_window, height=4, width=40)
        desc_text.grid(row=4, column=1, pady=5, sticky=tk.W)

        def save_formula():
            category = new_category_var.get()
            if category == "新分类":
                category = new_cat_name_var.get()
                if not category:
                    messagebox.showerror("错误", "请输入新分类名称")
                    return
                self.formulas[category] = {}

            name = name_var.get()
            formula = formula_text.get(1.0, tk.END).strip()

            if not name or not formula:
                messagebox.showerror("错误", "请输入完整的公式信息")
                return

            if category in self.formulas and name in self.formulas[category]:
                messagebox.showerror("错误", "该公式已存在")
                return

            if category not in self.formulas:
                self.formulas[category] = {}

            self.formulas[category][name] = formula
            messagebox.showinfo("成功", "公式添加成功")
            add_window.destroy()
            self.update_formula_list()

        tk.Button(add_window, text="保存", command=save_formula,
                  bg="#4CAF50", fg="white", width=10).grid(row=5, column=0, columnspan=2, pady=20)

    def export_formulas(self):
        try:
            with open("formulas.json", "w", encoding="utf-8") as f:
                json.dump(self.formulas, f, ensure_ascii=False, indent=2)
            messagebox.showinfo("成功", f"公式已导出到 formulas.json")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {str(e)}")

    def import_formulas(self):
        try:
            if os.path.exists("formulas.json"):
                with open("formulas.json", "r", encoding="utf-8") as f:
                    imported = json.load(f)
                self.formulas.update(imported)
                messagebox.showinfo("成功", "公式导入成功")
                self.update_formula_list()
            else:
                messagebox.showwarning("提示", "未找到 formulas.json 文件")
        except Exception as e:
            messagebox.showerror("错误", f"导入失败: {str(e)}")


def main():
    root = tk.Tk()
    app = FormulaSearchApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()
