import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import json
import random
import os

# 示例诗库（仅少量示例）。完整数据请用 JSON 或 CSV 导入。
DEFAULT_POEMS = [
    {
        "title": "静夜思",
        "author": "李白",
        "dynasty": "唐",
        "text": "床前明月光，疑是地上霜。\\n举头望明月，低头思故乡。",
        "notes": "表达思乡之情，语言清新。"
    },
    {
        "title": "春晓",
        "author": "孟浩然",
        "dynasty": "唐",
        "text": "春眠不觉晓，处处闻啼鸟。\\n夜来风雨声，花落知多少。",
        "notes": "写春晨感受，意境恬淡。"
    },
    {
        "title": "望庐山瀑布",
        "author": "李白",
        "dynasty": "唐",
        "text": "日照香炉生紫烟，遥看瀑布挂前川。\\n飞流直下三千尺，疑是银河落九天。",
        "notes": ""
    },
    {
        "title": "送元二使安西",
        "author": "王维",
        "dynasty": "唐",
        "text": "渭城朝雨浥轻尘，客舍青青柳色新。\\n劝君更尽一杯酒，西出阳关无故人。",
        "notes": "送别诗名篇，常与“阳关”典故相关。"
    }
]

class Tang300App:
    def __init__(self, master):
        self.master = master
        master.title("唐诗三百首（简易版）")
        master.geometry("900x600")

        self.poems = DEFAULT_POEMS.copy()
        self.filtered = list(range(len(self.poems)))  # 当前列表中索引

        # 顶部工具栏：搜索、筛选、导入/导出
        toolbar = ttk.Frame(master)
        toolbar.pack(side=tk.TOP, fill=tk.X, padx=6, pady=6)

        ttk.Label(toolbar, text="搜索（诗名/作者）:").pack(side=tk.LEFT, padx=(2,4))
        self.search_var = tk.StringVar()
        search_entry = ttk.Entry(toolbar, textvariable=self.search_var, width=30)
        search_entry.pack(side=tk.LEFT, padx=(0,8))
        search_entry.bind("<Return>", lambda e: self.do_search())
        ttk.Button(toolbar, text="搜索", command=self.do_search).pack(side=tk.LEFT, padx=4)
        ttk.Button(toolbar, text="全部", command=self.reset_filter).pack(side=tk.LEFT, padx=4)

        ttk.Label(toolbar, text="按朝代:").pack(side=tk.LEFT, padx=(12,4))
        self.dynasty_var = tk.StringVar(value="全部")
        dynasty_combo = ttk.Combobox(toolbar, textvariable=self.dynasty_var, width=10, state="readonly")
        dynasty_combo['values'] = ("全部", "唐")
        dynasty_combo.pack(side=tk.LEFT, padx=2)
        dynasty_combo.bind("<<ComboboxSelected>>", lambda e: self.apply_filters())

        ttk.Label(toolbar, text="按作者:").pack(side=tk.LEFT, padx=(12,4))
        self.author_var = tk.StringVar(value="全部")
        self.author_combo = ttk.Combobox(toolbar, textvariable=self.author_var, width=14, state="readonly")
        self.refresh_author_options()
        self.author_combo.pack(side=tk.LEFT, padx=2)
        self.author_combo.bind("<<ComboboxSelected>>", lambda e: self.apply_filters())

        ttk.Button(toolbar, text="导入 JSON", command=self.import_json).pack(side=tk.RIGHT, padx=4)
        ttk.Button(toolbar, text="导出 JSON", command=self.export_json).pack(side=tk.RIGHT, padx=4)

        # 主体左右分栏：左列表，右显示
        main_pane = ttk.Panedwindow(master, orient=tk.HORIZONTAL)
        main_pane.pack(fill=tk.BOTH, expand=True, padx=6, pady=6)

        left_frame = ttk.Frame(main_pane, width=250)
        right_frame = ttk.Frame(main_pane)
        main_pane.add(left_frame, weight=1)
        main_pane.add(right_frame, weight=3)

        # 左侧：诗目列表（可滚动）
        left_top = ttk.Frame(left_frame)
        left_top.pack(fill=tk.X)
        ttk.Label(left_top, text="诗目列表：").pack(side=tk.LEFT, padx=4, pady=4)
        ttk.Button(left_top, text="随机一首", command=self.open_random).pack(side=tk.RIGHT, padx=4)

        self.listbox = tk.Listbox(left_frame, exportselection=False)
        self.listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(4,0), pady=4)
        self.listbox.bind("<<ListboxSelect>>", lambda e: self.on_select())

        scrollbar = ttk.Scrollbar(left_frame, orient=tk.VERTICAL, command=self.listbox.yview)
        scrollbar.pack(side=tk.LEFT, fill=tk.Y)
        self.listbox.config(yscrollcommand=scrollbar.set)

        # 右侧：诗文显示区，带控制按钮
        right_top = ttk.Frame(right_frame)
        right_top.pack(fill=tk.X, pady=(0,4))
        ttk.Button(right_top, text="上一首", command=self.open_prev).pack(side=tk.LEFT, padx=4)
        ttk.Button(right_top, text="下一首", command=self.open_next).pack(side=tk.LEFT, padx=4)
        self.show_notes_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(right_top, text="显示注释", variable=self.show_notes_var, command=self.refresh_display).pack(side=tk.LEFT, padx=8)
        ttk.Button(right_top, text="添加/编辑诗", command=self.edit_current_poem).pack(side=tk.RIGHT, padx=4)
        ttk.Button(right_top, text="删除诗", command=self.delete_current_poem).pack(side=tk.RIGHT, padx=4)

        # 标题与作者显示
        title_frame = ttk.Frame(right_frame)
        title_frame.pack(fill=tk.X, pady=(0,4))
        self.title_label = ttk.Label(title_frame, text="", font=("Helvetica", 16, "bold"))
        self.title_label.pack(side=tk.LEFT, padx=6)
        self.author_label = ttk.Label(title_frame, text="", font=("Helvetica", 12))
        self.author_label.pack(side=tk.RIGHT, padx=6)

        # 诗文文本
        self.text_widget = tk.Text(right_frame, wrap=tk.WORD, state=tk.DISABLED, font=("SimSun", 14))
        self.text_widget.pack(fill=tk.BOTH, expand=True, padx=6, pady=6)

        # 刷新列表并默认选中第一项
        self.refresh_listbox()
        if self.listbox.size() > 0:
            self.listbox.selection_set(0)
            self.on_select()

    def refresh_author_options(self):
        authors = sorted({p["author"] for p in self.poems if p.get("author")})
        values = ["全部"] + authors
        try:
            self.author_combo['values'] = values
        except Exception:
            pass

    def refresh_listbox(self):
        self.listbox.delete(0, tk.END)
        self.filtered = []
        q = self.search_var.get().strip().lower()
        dynasty = self.dynasty_var.get()
        author = self.author_var.get()
        for idx, p in enumerate(self.poems):
            if dynasty and dynasty != "全部" and p.get("dynasty") != dynasty:
                continue
            if author and author != "全部" and p.get("author") != author:
                continue
            if q:
                if q not in (p.get("title","")+" "+p.get("author","")).lower():
                    continue
            display = f"{p.get('title','')} — {p.get('author','')}"
            self.listbox.insert(tk.END, display)
            self.filtered.append(idx)

    def do_search(self):
        self.refresh_listbox()
        if self.listbox.size() > 0:
            self.listbox.selection_set(0)
            self.on_select()

    def reset_filter(self):
        self.search_var.set("")
        self.dynasty_var.set("全部")
        self.author_var.set("全部")
        self.refresh_listbox()
        if self.listbox.size() > 0:
            self.listbox.selection_set(0)
            self.on_select()

    def apply_filters(self):
        self.refresh_listbox()
        if self.listbox.size() > 0:
            self.listbox.selection_set(0)
            self.on_select()

    def on_select(self):
        sel = self.listbox.curselection()
        if not sel:
            return
        pos = sel[0]
        real_idx = self.filtered[pos]
        self.open_poem_by_index(real_idx)

    def open_poem_by_index(self, idx):
        if idx < 0 or idx >= len(self.poems):
            return
        p = self.poems[idx]
        self.current_index = idx
        self.title_label.config(text=p.get("title",""))
        author = p.get("author","")
        dynasty = p.get("dynasty","")
        self.author_label.config(text=f"{author}  {dynasty}")
        self.refresh_display()

    def refresh_display(self):
        if not hasattr(self, "current_index"):
            return
        p = self.poems[self.current_index]
        text = p.get("text","")
        notes = p.get("notes","")
        show_notes = self.show_notes_var.get()

        self.text_widget.config(state=tk.NORMAL)
        self.text_widget.delete("1.0", tk.END)
        for line in text.split("\\n"):
            self.text_widget.insert(tk.END, line + "\n")
        if show_notes and notes:
            self.text_widget.insert(tk.END, "\n注：\n" + notes + "\n")
        self.text_widget.config(state=tk.DISABLED)

    def open_prev(self):
        if not hasattr(self, "current_index"):
            return
        # 在 filtered 列表中找到当前项的位置，然后选上一个
        try:
            cur_pos = self.filtered.index(self.current_index)
            new_pos = max(0, cur_pos - 1)
            self.listbox.selection_clear(0, tk.END)
            self.listbox.selection_set(new_pos)
            self.listbox.see(new_pos)
            self.on_select()
        except ValueError:
            pass

    def open_next(self):
        if not hasattr(self, "current_index"):
            return
        try:
            cur_pos = self.filtered.index(self.current_index)
            new_pos = min(len(self.filtered)-1, cur_pos + 1)
            self.listbox.selection_clear(0, tk.END)
            self.listbox.selection_set(new_pos)
            self.listbox.see(new_pos)
            self.on_select()
        except ValueError:
            pass

    def open_random(self):
        if not self.filtered:
            return
        pos = random.randrange(len(self.filtered))
        self.listbox.selection_clear(0, tk.END)
        self.listbox.selection_set(pos)
        self.listbox.see(pos)
        self.on_select()

    def import_json(self):
        path = filedialog.askopenfilename(title="导入诗库（JSON）", filetypes=[("JSON 文件", "*.json"),("所有文件","*.*")])
        if not path:
            return
        try:
            with open(path, "r", encoding="utf-8") as f:
                data = json.load(f)
            if not isinstance(data, list):
                messagebox.showerror("错误", "JSON 文件格式应为诗歌对象列表")
                return
            # 简单校验每项应当包含 title 和 text
            for item in data:
                if "title" not in item or "text" not in item:
                    messagebox.showerror("错误", "每首诗应包含 title 和 text 字段")
                    return
            self.poems = data
            self.refresh_author_options()
            self.refresh_listbox()
            messagebox.showinfo("导入成功", f"从 {os.path.basename(path)} 导入 {len(self.poems)} 首诗")
        except Exception as e:
            messagebox.showerror("导入失败", str(e))

    def export_json(self):
        path = filedialog.asksaveasfilename(title="导出诗库（JSON）", defaultextension=".json",
                                            filetypes=[("JSON 文件", "*.json"),("所有文件","*.*")])
        if not path:
            return
        try:
            with open(path, "w", encoding="utf-8") as f:
                json.dump(self.poems, f, ensure_ascii=False, indent=2)
            messagebox.showinfo("导出成功", f"已保存到 {path}")
        except Exception as e:
            messagebox.showerror("导出失败", str(e))

    def edit_current_poem(self):
        # 弹出窗口，编辑或添加诗歌
        def save_edit():
            title = title_var.get().strip()
            author = author_var.get().strip()
            dynasty = dynasty_var.get().strip()
            text = text_var.get("1.0", tk.END).strip()
            notes = notes_var.get("1.0", tk.END).strip()
            if not title or not text:
                messagebox.showwarning("提示", "标题与诗文不能为空")
                return
            obj = {"title": title, "author": author, "dynasty": dynasty or "唐", "text": text.replace("\n", "\\n"), "notes": notes}
            if editing_existing[0]:
                self.poems[self.current_index] = obj
            else:
                self.poems.append(obj)
            self.refresh_author_options()
            self.refresh_listbox()
            editor.destroy()

        editing_existing = [False]
        editor = tk.Toplevel(self.master)
        editor.title("编辑 / 添加 诗")
        editor.geometry("600x500")

        title_var = tk.StringVar()
        author_var = tk.StringVar()
        dynasty_var = tk.StringVar(value="唐")

        ttk.Label(editor, text="标题：").pack(anchor=tk.W, padx=6, pady=(6,0))
        ttk.Entry(editor, textvariable=title_var).pack(fill=tk.X, padx=6)

        ttk.Label(editor, text="作者：").pack(anchor=tk.W, padx=6, pady=(6,0))
        ttk.Entry(editor, textvariable=author_var).pack(fill=tk.X, padx=6)

        ttk.Label(editor, text="朝代：").pack(anchor=tk.W, padx=6, pady=(6,0))
        ttk.Entry(editor, textvariable=dynasty_var).pack(fill=tk.X, padx=6)

        ttk.Label(editor, text="诗文（多行）：").pack(anchor=tk.W, padx=6, pady=(6,0))
        text_var = tk.Text(editor, height=8)
        text_var.pack(fill=tk.BOTH, expand=False, padx=6, pady=(0,6))

        ttk.Label(editor, text="注释（可选）：").pack(anchor=tk.W, padx=6, pady=(6,0))
        notes_var = tk.Text(editor, height=6)
        notes_var.pack(fill=tk.BOTH, expand=False, padx=6, pady=(0,6))

        btn_frame = ttk.Frame(editor)
        btn_frame.pack(fill=tk.X, pady=6)
        ttk.Button(btn_frame, text="保存", command=save_edit).pack(side=tk.RIGHT, padx=6)
        ttk.Button(btn_frame, text="取消", command=editor.destroy).pack(side=tk.RIGHT)

        # 如果已有当前项则加载数据以编辑
        if hasattr(self, "current_index"):
            p = self.poems[self.current_index]
            title_var.set(p.get("title",""))
            author_var.set(p.get("author",""))
            dynasty_var.set(p.get("dynasty","唐"))
            text_var.insert("1.0", p.get("text","").replace("\\n", "\n"))
            notes_var.insert("1.0", p.get("notes",""))
            editing_existing[0] = True
        else:
            editing_existing[0] = False

    def delete_current_poem(self):
        if not hasattr(self, "current_index"):
            return
        if not messagebox.askyesno("确认删除", "确定删除当前诗吗？"):
            return
        del self.poems[self.current_index]
        self.refresh_author_options()
        self.refresh_listbox()
        # 重置选择
        if self.listbox.size() > 0:
            self.listbox.selection_set(0)
            self.on_select()
        else:
            self.title_label.config(text="")
            self.author_label.config(text="")
            self.text_widget.config(state=tk.NORMAL)
            self.text_widget.delete("1.0", tk.END)
            self.text_widget.config(state=tk.DISABLED)

if __name__ == "__main__":
    root = tk.Tk()
    app = Tang300App(root)
    root.mainloop()