# -*- coding: utf-8 -*-
import tkinter as tk
from tkinter import ttk, messagebox
import random
import time


class TypingPracticeApp:
    def __init__(self, root):
        self.root = root
        self.root.title("打字练习软件")
        self.root.geometry("900x700")
        self.root.configure(bg="#1a1a2e")

        # 练习文本库
        self.text_samples = {
            "简单英文": [
                "the quick brown fox jumps over the lazy dog",
                "hello world this is a simple typing practice test",
                "practice makes perfect and consistency is the key to success",
                "coding is fun and python is a great programming language",
                "the sun rises in the east and sets in the west every day",
            ],
            "中等英文": [
                "The development of artificial intelligence has transformed many industries across the globe.",
                "Programming requires patience, logical thinking, and the ability to solve complex problems efficiently.",
                "In the modern digital age, data has become one of the most valuable resources for any organization.",
                "The combination of creativity and technical skills can lead to amazing innovations in software design.",
                "We are living in an era where technology evolves at a pace that challenges even the brightest minds.",
            ],
            "困难英文": [
                "Quantum computing represents a paradigm shift in computational capabilities, leveraging superposition and entanglement.",
                "The epistemological foundations of machine learning algorithms necessitate rigorous validation methodologies.",
                "Sophisticated neural architectures have demonstrated remarkable proficiency in natural language understanding tasks.",
                "Cybersecurity protocols must evolve concurrently with emerging threat vectors in the digital landscape.",
                "The intersection of biotechnology and information systems heralds unprecedented opportunities for medical advancement.",
            ],
            "简单中文": [
                "今天天气晴朗，阳光透过窗户洒在桌面上，温暖而舒适。",
                "学习编程需要耐心和坚持，每天进步一点点，积累起来就是巨大的收获。",
                "我喜欢在安静的午后，泡一杯茶，读一本好书，享受独处的时光。",
                "这个程序的功能很简单，但实现过程中却让我学到了很多新知识。",
                "春暖花开的季节，最适合去郊外踏青，感受大自然的美好馈赠。",
            ],
            "中等中文": [
                "在这个信息爆炸的时代，能够快速准确地获取和处理信息变得越来越重要。",
                "软件开发不仅仅是编写代码，更是一个系统性工程，需要考虑架构、性能和可维护性。",
                "人工智能技术的发展正在重塑传统行业的生产方式，也为创业者带来了新的机遇。",
                "良好的学习习惯是在长期实践中形成的，它需要自律、好奇心和持续反思的结合。",
                "当我们面对复杂问题时，将其分解为若干个小任务逐个击破，往往是最高效的策略。",
            ],
            "困难中文": [
                "量子力学所揭示的微观世界规律与我们日常经验截然不同，挑战着人类对现实的认知边界。",
                "数字化转型的本质在于重构组织的价值创造方式，而非简单地在技术层面进行修补或改良。",
                "当代哲学对意识本质的探讨已经深入到神经科学与人工智能交叉的前沿地带。",
                "宏观经济政策的制定需要在稳增长、控通胀、促就业等多重目标之间寻求精妙的平衡。",
                "后现代主义思潮对传统叙事方式的消解，为我们重新审视历史与文化提供了全新的视角。",
            ]
        }

        self.current_text = ""
        self.typed_chars = []
        self.start_time = None
        self.is_typing = False
        self.timer_running = False

        self.setup_ui()

    def setup_ui(self):
        # 标题
        title_frame = tk.Frame(self.root, bg="#1a1a2e")
        title_frame.pack(pady=15)

        tk.Label(
            title_frame,
            text="打字练习软件",
            font=("Microsoft YaHei", 24, "bold"),
            bg="#1a1a2e",
            fg="#00d9ff"
        ).pack()

        tk.Label(
            title_frame,
            text="Typing Practice Software",
            font=("Arial", 10),
            bg="#1a1a2e",
            fg="#666680"
        ).pack()

        # 控制面板
        control_frame = tk.Frame(self.root, bg="#16213e", relief=tk.FLAT, bd=2)
        control_frame.pack(fill=tk.X, padx=20, pady=10)

        # 难度选择
        tk.Label(
            control_frame,
            text="难度:",
            font=("Microsoft YaHei", 11),
            bg="#16213e",
            fg="#ffffff"
        ).pack(side=tk.LEFT, padx=15, pady=10)

        self.difficulty_var = tk.StringVar(value="简单英文")
        difficulty_combo = ttk.Combobox(
            control_frame,
            textvariable=self.difficulty_var,
            values=["简单英文", "中等英文", "困难英文", "简单中文", "中等中文", "困难中文"],
            state="readonly",
            width=12,
            font=("Microsoft YaHei", 10)
        )
        difficulty_combo.pack(side=tk.LEFT, padx=5, pady=10)
        difficulty_combo.bind("<<ComboboxSelected>>", self.change_difficulty)

        # 分隔线
        separator1 = tk.Frame(control_frame, bg="#444466", width=2)
        separator1.pack(side=tk.LEFT, fill=tk.Y, padx=15, pady=10)

        # 计时模式
        tk.Label(
            control_frame,
            text="计时:",
            font=("Microsoft YaHei", 11),
            bg="#16213e",
            fg="#ffffff"
        ).pack(side=tk.LEFT, padx=5, pady=10)

        self.timer_var = tk.IntVar(value=60)
        timer_options = [30, 60, 120, 180]
        timer_menu = ttk.Combobox(
            control_frame,
            textvariable=self.timer_var,
            values=timer_options,
            state="readonly",
            width=8,
            font=("Microsoft YaHei", 10)
        )
        timer_menu.pack(side=tk.LEFT, padx=5, pady=10)

        # 分隔线
        separator2 = tk.Frame(control_frame, bg="#444466", width=2)
        separator2.pack(side=tk.LEFT, fill=tk.Y, padx=15, pady=10)

        # 按钮
        start_btn = tk.Button(
            control_frame,
            text="开始练习",
            command=self.start_practice,
            font=("Microsoft YaHei", 11, "bold"),
            bg="#00d26a",
            fg="white",
            padx=20,
            pady=8,
            cursor="hand2",
            relief=tk.FLAT
        )
        start_btn.pack(side=tk.LEFT, padx=10, pady=10)

        reset_btn = tk.Button(
            control_frame,
            text="重新开始",
            command=self.reset_practice,
            font=("Microsoft YaHei", 11),
            bg="#ff9500",
            fg="white",
            padx=20,
            pady=8,
            cursor="hand2",
            relief=tk.FLAT
        )
        reset_btn.pack(side=tk.LEFT, padx=10, pady=10)

        # 统计面板
        stats_frame = tk.Frame(self.root, bg="#16213e", relief=tk.FLAT, bd=2)
        stats_frame.pack(fill=tk.X, padx=20, pady=5)

        # 统计数据标签
        self.stats_labels = {}
        stats_items = [
            ("time_left", "剩余时间:", "--"),
            ("wpm", "每分钟字数(WPM):", "0"),
            ("accuracy", "准确率(%):", "100"),
            ("chars_typed", "已输入:", "0"),
            ("errors", "错误:", "0"),
        ]

        for i, (key, label, value) in enumerate(stats_items):
            frame = tk.Frame(stats_frame, bg="#16213e")
            frame.grid(row=0, column=i, padx=20, pady=10, sticky="nsew")

            tk.Label(
                frame,
                text=label,
                font=("Microsoft YaHei", 9),
                bg="#16213e",
                fg="#8888aa"
            ).pack()

            self.stats_labels[key] = tk.Label(
                frame,
                text=value,
                font=("Consolas", 16, "bold"),
                bg="#16213e",
                fg="#00d9ff"
            )
            self.stats_labels[key].pack()

        # 配置列权重
        for i in range(len(stats_items)):
            stats_frame.columnconfigure(i, weight=1)

        # 文本显示区域
        text_frame = tk.Frame(self.root, bg="#1a1a2e")
        text_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)

        tk.Label(
            text_frame,
            text="练习文本:",
            font=("Microsoft YaHei", 11, "bold"),
            bg="#1a1a2e",
            fg="#ffffff"
        ).pack(anchor=tk.W)

        # 文本显示文本框
        self.text_display = tk.Text(
            text_frame,
            font=("Consolas", 14),
            bg="#0f0f23",
            fg="#cccccc",
            wrap=tk.WORD,
            height=6,
            relief=tk.FLAT,
            bd=2,
            padx=15,
            pady=15
        )
        self.text_display.pack(fill=tk.BOTH, expand=True, pady=5)
        self.text_display.config(state=tk.DISABLED)

        # 输入区域
        input_frame = tk.Frame(self.root, bg="#1a1a2e")
        input_frame.pack(fill=tk.X, padx=20, pady=10)

        tk.Label(
            input_frame,
            text="在此输入:",
            font=("Microsoft YaHei", 11, "bold"),
            bg="#1a1a2e",
            fg="#ffffff"
        ).pack(anchor=tk.W)

        self.input_entry = tk.Entry(
            input_frame,
            font=("Consolas", 14),
            bg="#0f0f23",
            fg="#00ff88",
            insertbackground="#00ff88",
            relief=tk.FLAT,
            bd=2,
            disabledbackground="#0f0f23",
            disabledforeground="#00ff88"
        )
        self.input_entry.pack(fill=tk.X, pady=5)
        self.input_entry.config(state=tk.DISABLED)
        self.input_entry.bind("<KeyRelease>", self.check_typing)

        # 进度条
        progress_frame = tk.Frame(self.root, bg="#1a1a2e")
        progress_frame.pack(fill=tk.X, padx=20, pady=5)

        tk.Label(
            progress_frame,
            text="进度:",
            font=("Microsoft YaHei", 9),
            bg="#1a1a2e",
            fg="#8888aa"
        ).pack(anchor=tk.W)

        self.progress_var = tk.DoubleVar(value=0)
        self.progress_bar = ttk.Progressbar(
            progress_frame,
            variable=self.progress_var,
            maximum=100,
            length=400,
            mode='determinate'
        )
        self.progress_bar.pack(fill=tk.X, pady=5)

        # 底部状态栏
        status_frame = tk.Frame(self.root, bg="#0f0f23")
        status_frame.pack(fill=tk.X, side=tk.BOTTOM)

        self.status_label = tk.Label(
            status_frame,
            text="提示: 选择难度后点击「开始练习」按钮开始打字测试",
            font=("Microsoft YaHei", 9),
            bg="#0f0f23",
            fg="#666680",
            anchor=tk.W,
            padx=15,
            pady=8
        )
        self.status_label.pack(fill=tk.X)

    def change_difficulty(self, event=None):
        """切换难度时重置练习"""
        if not self.is_typing:
            self.load_new_text()

    def load_new_text(self):
        """加载新文本"""
        difficulty = self.difficulty_var.get()
        texts = self.text_samples[difficulty]
        self.current_text = random.choice(texts)

        # 显示文本
        self.text_display.config(state=tk.NORMAL)
        self.text_display.delete(1.0, tk.END)
        self.text_display.insert(1.0, self.current_text)
        self.text_display.config(state=tk.DISABLED)

        # 重置统计
        self.typed_chars = []
        self.update_stats()

    def start_practice(self):
        """开始练习"""
        self.load_new_text()
        self.input_entry.config(state=tk.NORMAL)
        self.input_entry.delete(0, tk.END)
        self.input_entry.focus()

        self.is_typing = True
        self.start_time = time.time()
        self.timer_running = True

        # 启动计时器
        self.update_timer()

        self.status_label.config(text="练习进行中... 开始打字吧！")

    def reset_practice(self):
        """重置练习"""
        self.timer_running = False
        self.is_typing = False
        self.start_time = None
        self.typed_chars = []

        self.input_entry.config(state=tk.DISABLED)
        self.input_entry.delete(0, tk.END)

        self.progress_var.set(0)

        self.stats_labels["time_left"].config(text="--")
        self.stats_labels["wpm"].config(text="0")
        self.stats_labels["accuracy"].config(text="100")
        self.stats_labels["chars_typed"].config(text="0")
        self.stats_labels["errors"].config(text="0")

        self.status_label.config(text="练习已重置，点击「开始练习」重新开始")

    def update_timer(self):
        """更新计时器"""
        if not self.timer_running:
            return

        elapsed = time.time() - self.start_time
        remaining = max(0, self.timer_var.get() - elapsed)

        self.stats_labels["time_left"].config(text=f"{int(remaining)}秒")

        if remaining <= 0:
            self.finish_practice()
        else:
            self.root.after(100, self.update_timer)

    def check_typing(self, event=None):
        """检查打字输入"""
        if not self.is_typing:
            return

        typed = self.input_entry.get()
        target = self.current_text

        # 更新已输入字符
        self.typed_chars = list(typed)

        # 计算统计数据
        correct_chars = 0
        errors = 0

        for i, char in enumerate(typed):
            if i < len(target):
                if char == target[i]:
                    correct_chars += 1
                else:
                    errors += 1

        total_chars = len(typed)
        accuracy = (correct_chars / total_chars *
                    100) if total_chars > 0 else 100

        # 计算WPM (每分钟字数)
        elapsed_minutes = (time.time() - self.start_time) / 60
        wpm = int(correct_chars / 5 /
                  elapsed_minutes) if elapsed_minutes > 0 else 0

        # 更新统计显示
        self.stats_labels["wpm"].config(text=str(wpm))
        self.stats_labels["accuracy"].config(text=f"{accuracy:.1f}")
        self.stats_labels["chars_typed"].config(text=str(total_chars))
        self.stats_labels["errors"].config(text=str(errors))

        # 更新进度条
        progress = (len(typed) / len(target)) * 100
        self.progress_var.set(min(progress, 100))

        # 更新文本显示（高亮）
        self.highlight_text(typed, target)

        # 检查是否完成
        if typed == target:
            self.finish_practice()

    def highlight_text(self, typed, target):
        """高亮显示文本"""
        self.text_display.config(state=tk.NORMAL)
        self.text_display.delete(1.0, tk.END)

        for i, char in enumerate(target):
            if i < len(typed):
                if typed[i] == char:
                    # 正确字符 - 绿色
                    self.text_display.insert(tk.END, char, "correct")
                else:
                    # 错误字符 - 红色
                    self.text_display.insert(tk.END, char, "wrong")
            elif i == len(typed):
                # 当前位置 - 光标
                self.text_display.insert(tk.END, char, "current")
            else:
                # 未输入字符 - 灰色
                self.text_display.insert(tk.END, char, "pending")

        self.text_display.config(state=tk.DISABLED)

    def finish_practice(self):
        """完成练习"""
        self.timer_running = False
        self.is_typing = False
        self.input_entry.config(state=tk.DISABLED)

        # 计算最终成绩
        elapsed = time.time() - self.start_time
        elapsed_minutes = elapsed / 60

        total_typed = len(self.typed_chars)
        correct_chars = sum(1 for i, c in enumerate(self.typed_chars)
                            if i < len(self.current_text) and c == self.current_text[i])

        final_wpm = int(correct_chars / 5 /
                        elapsed_minutes) if elapsed_minutes > 0 else 0
        final_accuracy = (correct_chars / total_typed *
                          100) if total_typed > 0 else 100

        # 显示结果
        result_msg = f"""
========================================
           练习完成！
========================================
总用时: {elapsed:.1f} 秒
每分钟字数(WPM): {final_wpm}
准确率: {final_accuracy:.1f}%
正确字符: {correct_chars} / {total_typed}
========================================
        """

        self.status_label.config(
            text=f"练习完成！WPM: {final_wpm}, 准确率: {final_accuracy:.1f}%")

        # 弹出结果窗口
        messagebox.showinfo("练习结果", result_msg.strip())

    def update_stats(self):
        """更新统计数据"""
        self.stats_labels["time_left"].config(text="--")
        self.stats_labels["wpm"].config(text="0")
        self.stats_labels["accuracy"].config(text="100")
        self.stats_labels["chars_typed"].config(text="0")
        self.stats_labels["errors"].config(text="0")


def main():
    root = tk.Tk()
    app = TypingPracticeApp(root)

    # 配置文本标签样式
    root.option_add("*Text.Background", "#0f0f23")
    root.option_add("*Text.Foreground", "#cccccc")

    style = ttk.Style()
    style.theme_use('clam')

    root.mainloop()


if __name__ == "__main__":
    main()
