#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
唐诗浏览器（单窗口切换显示）
- 左侧：诗目列表（支持搜索）
- 右侧：选中诗歌的 原文 / 释义 / 诗人背景 / 赏析（即时切换，不弹新窗口）
- 默认包含若干示例诗；可从同目录 tang300.json 或任意 JSON 文件加载完整数据
JSON 项目格式建议：
[
  {
    "title": "静夜思",
    "author": "李白",
    "text": "床前明月光，疑是地上霜。\n举头望明月，低头思故乡。",
    "annotation": "释义或译文...",
    "bio": "诗人简介...",
    "commentary": "赏析或亮点..."
  },
  ...
]
"""

import json
import os
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from tkinter.scrolledtext import ScrolledText

# ---------- 内置示例（演示用，建议替换为完整 tang300.json） ----------
SAMPLE_POEMS = [
    {
        "title": "静夜思",
        "author": "李白",
        "text": "床前明月光，疑是地上霜。\n举头望明月，低头思故乡。",
        "annotation": "床前有明亮的月光，像是地上的霜。抬头望着明月，低头思念家乡。",
        "bio": "李白（701–762），盛唐浪漫主义诗人，号“诗仙”。",
        "commentary": "以简洁语言抒发强烈乡愁，意境清远、镜头集中，极易传诵。"
    },
    {
        "title": "春晓",
        "author": "孟浩然",
        "text": "春眠不觉晓，处处闻啼鸟。\n夜来风雨声，花落知多少。",
        "annotation": "春天睡得不知天已亮，到处都是鸟鸣。昨夜风雨，花落多少不得而知。",
        "bio": "孟浩然（689–740），山水田园诗派代表，诗风自然淡雅。",
        "commentary": "画面简洁、节律鲜明，生活气息浓厚，常作为入门名篇。"
    },
    # 你可以在此处继续添加更多示例条目
]

# ---------- GUI 应用 ----------


class TangPoemsBrowser(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("唐诗三百首 浏览器（单窗口显示）")
        self.geometry("1000x650")
        self.minsize(800, 500)
        self._poems = []
        self.load_data_from_list(SAMPLE_POEMS)
        self.try_auto_load_tang300()
        self._build_ui()

    def try_auto_load_tang300(self):
        # 如果程序目录下存在 tang300.json，则尝试加载覆盖内置示例
        fn = os.path.join(os.path.dirname(__file__), "tang300.json")
        if os.path.exists(fn):
            try:
                with open(fn, "r", encoding="utf-8") as f:
                    data = json.load(f)
                if isinstance(data, list) and data:
                    self.load_data_from_list(data)
                    messagebox.showinfo("已加载", "检测到 tang300.json 并已加载诗歌数据。")
            except Exception as e:
                messagebox.showwarning("加载失败", f"尝试自动加载 tang300.json 时出错：{e}")

    def load_data_from_list(self, poems):
        # poems: list of dicts
        self._poems = poems.copy()
        # build display items
        self._items = [
            f"{p.get('title','')} — {p.get('author','')}" for p in self._poems]
        # filtered index initially all
        self.filtered_indexes = list(range(len(self._items)))

    def _build_ui(self):
        # Top: search bar and load button
        top = ttk.Frame(self, padding=6)
        top.pack(side=tk.TOP, fill=tk.X)

        ttk.Label(top, text="搜索（标题/作者/正文/注释）:").pack(side=tk.LEFT)
        self.search_var = tk.StringVar()
        search_entry = ttk.Entry(top, textvariable=self.search_var, width=48)
        search_entry.pack(side=tk.LEFT, padx=(6, 8))
        search_entry.bind("<KeyRelease>", lambda e: self.on_search())

        load_btn = ttk.Button(top, text="加载 JSON 文件...",
                              command=self.load_from_file)
        load_btn.pack(side=tk.RIGHT)

        # Main: left list + right display
        main = ttk.Frame(self)
        main.pack(fill=tk.BOTH, expand=True, padx=6, pady=6)

        # Left frame: listbox
        left = ttk.Frame(main, width=320)
        left.pack(side=tk.LEFT, fill=tk.Y)
        ttk.Label(left, text="诗目列表", font=("Segoe UI", 10, "bold")
                  ).pack(anchor=tk.W, pady=(0, 4))

        self.listbox = tk.Listbox(left, exportselection=False)
        self.listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.listbox.bind("<<ListboxSelect>>", lambda e: self.on_select())
        self.listbox.bind("<Double-Button-1>", lambda e: self.on_select())

        lb_scroll = ttk.Scrollbar(
            left, orient=tk.VERTICAL, command=self.listbox.yview)
        lb_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        self.listbox.config(yscrollcommand=lb_scroll.set)

        # Right frame: display area (原文 / 注释 / 诗人背景 / 赏析)，使用 Notebook（选项卡）或垂直布局
        right = ttk.Frame(main)
        right.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(8, 0))

        # Header: title and author
        header = ttk.Frame(right)
        header.pack(fill=tk.X)
        self.title_var = tk.StringVar(value="请选择左侧诗目")
        ttk.Label(header, textvariable=self.title_var, font=(
            "Segoe UI", 12, "bold")).pack(anchor=tk.W)

        # Use a ScrolledText for combined display with sections
        self.display = ScrolledText(right, wrap='word', font=("宋体", 13))
        self.display.pack(fill=tk.BOTH, expand=True, pady=(6, 0))
        self.display.config(state='disabled')

        # Bottom: quick-buttons
        bottom = ttk.Frame(self)
        bottom.pack(side=tk.BOTTOM, fill=tk.X)
        self.status_var = tk.StringVar(value=f"共 {len(self._poems)} 首（示例或已加载）")
        ttk.Label(bottom, textvariable=self.status_var,
                  relief=tk.SUNKEN, anchor=tk.W).pack(fill=tk.X)

        # fill listbox
        self.refresh_listbox()

    def refresh_listbox(self):
        self.listbox.delete(0, tk.END)
        for idx in self.filtered_indexes:
            self.listbox.insert(tk.END, self._items[idx])
        self.status_var.set(
            f"匹配 {len(self.filtered_indexes)} / 总 {len(self._poems)} 首")

    def on_search(self):
        q = self.search_var.get().strip().lower()
        if not q:
            self.filtered_indexes = list(range(len(self._items)))
        else:
            res = []
            for i, p in enumerate(self._poems):
                title = p.get("title", "").lower()
                author = p.get("author", "").lower()
                text = p.get("text", "").lower()
                annotation = (p.get("annotation", "") or "").lower()
                if q in title or q in author or q in text or q in annotation:
                    res.append(i)
            self.filtered_indexes = res
        self.refresh_listbox()

    def get_selected(self):
        sel = self.listbox.curselection()
        if not sel:
            return None
        idx = sel[0]
        real_idx = self.filtered_indexes[idx]
        return self._poems[real_idx]

    def on_select(self):
        poem = self.get_selected()
        if poem:
            self.show_poem_inline(poem)

    def show_poem_inline(self, poem):
        # 在右侧 display 区显示，不打开新窗口
        title = f"{poem.get('title','')} — {poem.get('author','')}"
        text = poem.get('text', '')
        annotation = poem.get('annotation', '（暂无释义）')
        bio = poem.get('bio', '（暂无诗人简介）')
        commentary = poem.get('commentary', '（暂无赏析）')

        content = []
        content.append(title + "\n")
        content.append("原文：\n" + text + "\n")
        content.append("释义 / 注释：\n" + annotation + "\n")
        content.append("诗人背景：\n" + bio + "\n")
        content.append("赏析 / 好的点：\n" + commentary + "\n")

        self.title_var.set(title)
        self.display.config(state='normal')
        self.display.delete('1.0', tk.END)
        self.display.insert(tk.END, "\n".join(content))
        self.display.config(state='disabled')

    def load_from_file(self):
        fn = filedialog.askopenfilename(title="选择 JSON 文件（tang300.json）",
                                        filetypes=[("JSON 文件", "*.json"), ("所有文件", "*.*")])
        if not fn:
            return
        try:
            with open(fn, "r", encoding="utf-8") as f:
                data = json.load(f)
            if not isinstance(data, list):
                raise ValueError("JSON 文件应为诗歌对象列表")
            # optional minimal validation
            ok = all(isinstance(it, dict)
                     and "title" in it and "text" in it for it in data)
            if not ok:
                if not messagebox.askyesno("数据可疑", "部分项目缺少 title 或 text 字段。是否仍然加载？"):
                    return
            self.load_data_from_list(data)
            self.on_search()  # refresh filtering/list
            messagebox.showinfo("加载完成", f"已加载 {len(self._poems)} 首诗")
        except Exception as e:
            messagebox.showerror("加载失败", str(e))


if __name__ == "__main__":
    app = TangPoemsBrowser()
    app.mainloop()
