import tkinter as tk
from tkinter import ttk, messagebox, font
import random
import time


class TypingTutorApp:
    def __init__(self, root):
        self.root = root
        # 标题也去掉了 Emoji
        self.root.title("Python 打字练习大师")
        self.root.geometry("900x650")
        self.root.resizable(False, False)

        # --- 配置数据 ---
        self.sample_texts = [
            "The quick brown fox jumps over the lazy dog. This is a classic pangram used to test typewriters and computer keyboards.",
            "Python is an interpreted high-level general-purpose programming language. Its design philosophy emphasizes code readability with its use of significant indentation.",
            "Success is not final, failure is not fatal: it is the courage to continue that counts. Keep practicing and you will improve your typing speed.",
            "In the middle of difficulty lies opportunity. Do not watch the clock; do what it does. Keep going.",
            "Technology is best when it brings people together. It has become appallingly obvious that our technology has exceeded our humanity.",
            "The only way to do great work is to love what you do. If you haven't found it yet, keep looking. Don't settle.",
            "Artificial intelligence is the science and engineering of making intelligent machines, especially intelligent computer programs."
        ]

        self.time_limit = 60  # 练习时长（秒）
        self.is_running = False
        self.start_time = 0
        self.current_text = ""
        self.typed_chars = 0
        self.errors = 0

        # --- 创建界面 ---
        self.create_widgets()
        self.reset_game()

    def create_widgets(self):
        # 顶部标题
        header_frame = tk.Frame(self.root, bg="#2c3e50", height=80)
        header_frame.pack(fill=tk.X)
        # 去掉了标题的 Emoji
        tk.Label(header_frame, text="打字速度训练", font=(
            "Arial", 24, "bold"), bg="#2c3e50", fg="white").pack(pady=20)

        # 状态栏 (时间，WPM, 准确率)
        stats_frame = tk.Frame(self.root, bg="#ecf0f1", height=60)
        stats_frame.pack(fill=tk.X)

        self.time_label = tk.Label(stats_frame, text=f"时间：{self.time_limit}s", font=(
            "Arial", 16, "bold"), bg="#ecf0f1", fg="#e74c3c")
        self.time_label.pack(side=tk.LEFT, padx=40, pady=15)

        self.wpm_label = tk.Label(stats_frame, text="WPM: 0", font=(
            "Arial", 16, "bold"), bg="#ecf0f1", fg="#2980b9")
        self.wpm_label.pack(side=tk.LEFT, padx=40, pady=15)

        self.acc_label = tk.Label(stats_frame, text="准确率：100%", font=(
            "Arial", 16, "bold"), bg="#ecf0f1", fg="#27ae60")
        self.acc_label.pack(side=tk.LEFT, padx=40, pady=15)

        # 重置按钮 - 去掉了 Emoji (🔄)
        self.reset_btn = tk.Button(stats_frame, text="重新开始", command=self.reset_game, font=(
            "Arial", 12), bg="#95a5a6", fg="white")
        self.reset_btn.pack(side=tk.RIGHT, padx=40, pady=15)

        # 文本显示区 (目标文本)
        text_frame = tk.LabelFrame(self.root, text="请录入以下文字", font=(
            "Arial", 14, "bold"), padx=10, pady=10)
        text_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)

        # 使用 Text 组件显示目标文本，并设置标签用于高亮
        self.target_text_widget = tk.Text(text_frame, height=8, font=(
            "Consolas", 16), wrap=tk.WORD, borderwidth=0, highlightthickness=0, bg="#fdfdfd")
        self.target_text_widget.pack(fill=tk.BOTH, expand=True)

        # 配置标签颜色
        self.target_text_widget.tag_configure(
            "correct", background="#d4edda", foreground="#155724")  # 绿色背景
        self.target_text_widget.tag_configure(
            "incorrect", background="#f8d7da", foreground="#721c24")  # 红色背景
        self.target_text_widget.tag_configure(
            "pending", background="#fdfdfd", foreground="#333333")
        self.target_text_widget.tag_configure(
            "current", underline=True)  # 当前字符下划线

        # 输入框
        input_frame = tk.Frame(self.root, bg="#ecf0f1", height=60)
        input_frame.pack(fill=tk.X, padx=20, pady=10)

        tk.Label(input_frame, text="在此输入:", font=("Arial", 14),
                 bg="#ecf0f1").pack(side=tk.LEFT, padx=10)
        self.input_entry = tk.Entry(
            input_frame, font=("Consolas", 16), width=50)
        self.input_entry.pack(side=tk.LEFT, padx=10, fill=tk.X, expand=True)
        self.input_entry.bind("<KeyRelease>", self.check_input)
        self.input_entry.config(state=tk.DISABLED)  # 初始禁用

        # 底部说明
        tk.Label(self.root, text="提示：开始打字后计时自动启动。完成后按 '重新开始' 进行下一轮。", font=(
            "Arial", 10), bg="#ecf0f1", fg="#7f8c8d").pack(side=tk.BOTTOM, fill=tk.X)

    def reset_game(self):
        """重置游戏状态"""
        self.is_running = False
        self.start_time = 0
        self.typed_chars = 0
        self.errors = 0

        # 随机选择一篇文章
        self.current_text = random.choice(self.sample_texts)

        # 更新目标文本显示
        self.target_text_widget.config(state=tk.NORMAL)
        self.target_text_widget.delete("1.0", tk.END)
        self.target_text_widget.insert(tk.END, self.current_text)
        self.target_text_widget.config(state=tk.DISABLED)

        # 清空输入框并启用
        self.input_entry.config(state=tk.NORMAL)
        self.input_entry.delete(0, tk.END)
        self.input_entry.focus_set()

        # 重置高亮
        self.highlight_text(0)

        # 重置统计数据
        self.time_label.config(text=f"时间：{self.time_limit}s")
        self.wpm_label.config(text="WPM: 0")
        self.acc_label.config(text="准确率：100%")
        # 按钮文字也确保没有 Emoji
        self.reset_btn.config(text="重新开始")

    def highlight_text(self, cursor_pos):
        """高亮已输入的文本"""
        self.target_text_widget.config(state=tk.NORMAL)
        self.target_text_widget.tag_remove("correct", "1.0", tk.END)
        self.target_text_widget.tag_remove("incorrect", "1.0", tk.END)
        self.target_text_widget.tag_remove("current", "1.0", tk.END)

        input_val = self.input_entry.get()
        len_val = len(input_val)

        # 标记正确和错误的字符
        for i in range(len_val):
            start_idx = f"1.{i}"
            end_idx = f"1.{i+1}"
            if i < len(self.current_text):
                if input_val[i] == self.current_text[i]:
                    self.target_text_widget.tag_add(
                        "correct", start_idx, end_idx)
                else:
                    self.target_text_widget.tag_add(
                        "incorrect", start_idx, end_idx)

        # 标记当前光标位置
        if len_val < len(self.current_text):
            current_idx = f"1.{len_val}"
            self.target_text_widget.tag_add("current", current_idx)

        self.target_text_widget.config(state=tk.DISABLED)

    def check_input(self, event=None):
        """检查输入并计算统计"""
        input_val = self.input_entry.get()
        current_len = len(input_val)
        target_len = len(self.current_text)

        # 如果还没开始且用户输入了第一个字符，启动计时
        if not self.is_running and current_len > 0:
            self.is_running = True
            self.start_time = time.time()
            self.start_timer()

        # 更新高亮
        self.highlight_text(current_len)

        # 统计错误数
        temp_errors = 0
        for i in range(current_len):
            if i >= target_len or input_val[i] != self.current_text[i]:
                temp_errors += 1
        self.errors = temp_errors
        self.typed_chars = current_len

        # 实时更新 WPM 和 准确率
        if self.is_running:
            self.update_stats()

        # 检查是否完成
        if current_len >= target_len:
            self.finish_game()

    def start_timer(self):
        """启动倒计时"""
        def update():
            if self.is_running:
                elapsed = time.time() - self.start_time
                remaining = max(0, self.time_limit - int(elapsed))
                self.time_label.config(text=f"时间：{remaining}s")

                if remaining <= 0:
                    self.finish_game()
                else:
                    self.root.after(1000, update)
        update()

    def update_stats(self):
        """计算并更新 WPM 和准确率"""
        elapsed_time = time.time() - self.start_time
        if elapsed_time < 1:
            return

        # WPM 计算公式
        wpm = round((self.typed_chars / 5) / (elapsed_time / 60))

        # 准确率
        accuracy = 0
        if self.typed_chars > 0:
            accuracy = round(
                ((self.typed_chars - self.errors) / self.typed_chars) * 100)

        self.wpm_label.config(text=f"WPM: {wpm}")
        self.acc_label.config(text=f"准确率：{accuracy}%")

    def finish_game(self):
        """游戏结束处理"""
        self.is_running = False
        self.input_entry.config(state=tk.DISABLED)
        self.reset_btn.config(text="再玩一次")

        elapsed_time = time.time() - self.start_time
        if elapsed_time < 1:
            elapsed_time = 1

        final_wpm = round((self.typed_chars / 5) / (elapsed_time / 60))
        final_acc = 0
        if self.typed_chars > 0:
            final_acc = round(
                ((self.typed_chars - self.errors) / self.typed_chars) * 100)

        # 结果消息也去掉了 Emoji
        msg = f"练习完成!\n\n时间：{self.time_limit}s\n速度：{final_wpm} WPM\n准确率：{final_acc}%\n"

        if final_wpm > 40 and final_acc > 90:
            msg += "\n表现优秀！你是打字高手！"
        elif final_wpm > 20:
            msg += "\n表现不错，继续加油！"
        else:
            msg += "\n多加练习，你会更快的！"

        messagebox.showinfo("结果统计", msg)


if __name__ == "__main__":
    root = tk.Tk()
    # 尝试修复某些系统下的 DPI 问题
    try:
        from ctypes import windll
        windll.shcore.SetProcessDpiAwareness(1)
    except:
        pass
    app = TypingTutorApp(root)
    root.mainloop()
