import pygame
import random
import sys

# 初始化Pygame
pygame.init()

# 颜色常量
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (128, 128, 128)
LIGHT_GRAY = (200, 200, 200)
DARK_GRAY = (100, 100, 100)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 50, 255)


class ColorMatchingGame:
    def __init__(self):
        # 窗口设置
        self.screen_width = 800
        self.screen_height = 600
        self.screen = pygame.display.set_mode(
            (self.screen_width, self.screen_height))
        pygame.display.set_caption("配色练习游戏 - 匹配目标颜色")

        # 字体
        self.font_large = pygame.font.Font(None, 48)
        self.font_medium = pygame.font.Font(None, 36)
        self.font_small = pygame.font.Font(None, 28)

        # 游戏变量
        self.target_color = [random.randint(0, 255) for _ in range(3)]
        self.current_color = [128, 128, 128]  # 起始灰色
        self.score = 0
        self.rounds = 0
        self.max_rounds = 5
        self.game_over = False

        # 滑块设置
        self.slider_red = Slider(
            150, 350, 500, 20, (255, 0, 0), self.current_color[0])
        self.slider_green = Slider(
            150, 400, 500, 20, (0, 255, 0), self.current_color[1])
        self.slider_blue = Slider(
            150, 450, 500, 20, (0, 0, 255), self.current_color[2])

        # 按钮设置
        self.submit_button = Button(
            300, 520, 200, 50, "提交配色", (0, 150, 0), (0, 200, 0))
        self.next_button = Button(
            300, 520, 200, 50, "下一题", (0, 150, 0), (0, 200, 0))
        self.play_again_button = Button(
            300, 520, 200, 50, "再玩一次", (0, 150, 0), (0, 200, 0))

        # 反馈信息
        self.feedback = ""
        self.feedback_time = 0
        self.show_result = False
        self.round_complete = False

        # 时钟
        self.clock = pygame.time.Clock()

    def calculate_score(self):
        """计算当前配色的分数（0-100分）"""
        diff = sum(
            abs(self.target_color[i] - self.current_color[i]) for i in range(3))
        # 最大差异是765（255*3），分数从100递减
        score = max(0, int(100 - (diff / 765) * 100))
        return score

    def update_current_color(self):
        """更新当前颜色值"""
        self.current_color[0] = self.slider_red.value
        self.current_color[1] = self.slider_green.value
        self.current_color[2] = self.slider_blue.value

    def submit_color(self):
        """提交当前配色"""
        if not self.round_complete and not self.game_over:
            score = self.calculate_score()
            self.score += score
            self.rounds += 1

            # 显示反馈
            if score == 100:
                self.feedback = f"完美匹配！获得100分！"
            elif score >= 80:
                self.feedback = f"很好！获得{score}分！"
            elif score >= 60:
                self.feedback = f"不错！获得{score}分！"
            else:
                self.feedback = f"还可以更好！获得{score}分！"

            self.feedback_time = pygame.time.get_ticks()
            self.show_result = True
            self.round_complete = True

            # 检查游戏是否结束
            if self.rounds >= self.max_rounds:
                self.game_over = True

    def next_round(self):
        """进入下一轮"""
        if self.round_complete and not self.game_over:
            self.target_color = [random.randint(0, 255) for _ in range(3)]
            self.current_color = [128, 128, 128]
            self.slider_red.value = 128
            self.slider_green.value = 128
            self.slider_blue.value = 128
            self.round_complete = False
            self.show_result = False
            self.feedback = ""

    def reset_game(self):
        """重置游戏"""
        self.target_color = [random.randint(0, 255) for _ in range(3)]
        self.current_color = [128, 128, 128]
        self.score = 0
        self.rounds = 0
        self.game_over = False
        self.round_complete = False
        self.show_result = False
        self.feedback = ""
        self.slider_red.value = 128
        self.slider_green.value = 128
        self.slider_blue.value = 128

    def draw_color_boxes(self):
        """绘制颜色显示框"""
        # 目标颜色框
        target_rect = pygame.Rect(50, 100, 200, 150)
        pygame.draw.rect(self.screen, self.target_color, target_rect)
        pygame.draw.rect(self.screen, BLACK, target_rect, 3)

        # 当前颜色框
        current_rect = pygame.Rect(550, 100, 200, 150)
        pygame.draw.rect(self.screen, self.current_color, current_rect)
        pygame.draw.rect(self.screen, BLACK, current_rect, 3)

        # 标签
        target_label = self.font_medium.render("目标颜色", True, BLACK)
        current_label = self.font_medium.render("你的配色", True, BLACK)
        self.screen.blit(target_label, (100, 70))
        self.screen.blit(current_label, (600, 70))

    def draw_score(self):
        """绘制分数信息"""
        # 当前分数
        score_text = self.font_large.render(f"总分: {self.score}", True, BLACK)
        self.screen.blit(score_text, (650, 20))

        # 回合数
        round_text = self.font_medium.render(
            f"第 {self.rounds}/{self.max_rounds} 轮", True, BLACK)
        self.screen.blit(round_text, (50, 20))

        # 本轮得分
        if self.show_result:
            round_score = self.calculate_score()
            round_score_text = self.font_medium.render(
                f"本轮得分: {round_score}", True, BLACK)
            self.screen.blit(round_score_text, (50, 60))

    def draw_feedback(self):
        """绘制反馈信息"""
        if self.feedback and pygame.time.get_ticks() - self.feedback_time < 3000:
            feedback_surface = self.font_medium.render(
                self.feedback, True, (0, 100, 0))
            feedback_rect = feedback_surface.get_rect(
                center=(self.screen_width // 2, 300))
            # 绘制背景
            pygame.draw.rect(self.screen, WHITE, feedback_rect.inflate(20, 10))
            pygame.draw.rect(self.screen, BLACK,
                             feedback_rect.inflate(20, 10), 2)
            self.screen.blit(feedback_surface, feedback_rect)

    def draw_instructions(self):
        """绘制操作说明"""
        instructions = [
            "使用滑块调整RGB值",
            "调整颜色匹配目标",
            "点击'提交配色'获得分数"
        ]
        y_offset = 280
        for instruction in instructions:
            text = self.font_small.render(instruction, True, DARK_GRAY)
            self.screen.blit(text, (50, y_offset))
            y_offset += 25

    def draw_game_over(self):
        """绘制游戏结束画面"""
        # 半透明覆盖层
        overlay = pygame.Surface((self.screen_width, self.screen_height))
        overlay.set_alpha(200)
        overlay.fill(WHITE)
        self.screen.blit(overlay, (0, 0))

        # 游戏结束文字
        game_over_text = self.font_large.render("游戏结束!", True, RED)
        game_over_rect = game_over_text.get_rect(
            center=(self.screen_width // 2, 200))
        self.screen.blit(game_over_text, game_over_rect)

        # 最终得分
        final_score_text = self.font_large.render(
            f"最终得分: {self.score}", True, BLACK)
        final_score_rect = final_score_text.get_rect(
            center=(self.screen_width // 2, 280))
        self.screen.blit(final_score_text, final_score_rect)

        # 平均分
        avg_score = self.score / self.max_rounds
        avg_score_text = self.font_medium.render(
            f"平均分: {avg_score:.1f}", True, BLACK)
        avg_score_rect = avg_score_text.get_rect(
            center=(self.screen_width // 2, 340))
        self.screen.blit(avg_score_text, avg_score_rect)

        # 评级
        if avg_score >= 90:
            rating = "卓越！色彩大师！"
            color = (255, 215, 0)
        elif avg_score >= 75:
            rating = "优秀！色彩感很好！"
            color = (0, 150, 0)
        elif avg_score >= 60:
            rating = "良好！继续练习！"
            color = (0, 100, 200)
        else:
            rating = "加油！多练习会更好！"
            color = (200, 50, 50)

        rating_text = self.font_medium.render(rating, True, color)
        rating_rect = rating_text.get_rect(
            center=(self.screen_width // 2, 400))
        self.screen.blit(rating_text, rating_rect)

    def run(self):
        """主游戏循环"""
        running = True

        while running:
            # 处理事件
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

                # 处理滑块和按钮事件
                if not self.game_over:
                    if not self.round_complete:
                        self.slider_red.handle_event(event)
                        self.slider_green.handle_event(event)
                        self.slider_blue.handle_event(event)
                        self.update_current_color()

                        if self.submit_button.handle_event(event):
                            self.submit_color()
                    else:
                        if self.next_button.handle_event(event):
                            self.next_round()
                else:
                    if self.play_again_button.handle_event(event):
                        self.reset_game()

            # 绘制
            self.screen.fill(WHITE)

            # 绘制颜色框
            self.draw_color_boxes()

            # 绘制滑块
            self.slider_red.draw(self.screen)
            self.slider_green.draw(self.screen)
            self.slider_blue.draw(self.screen)

            # 绘制分数
            self.draw_score()

            # 绘制说明
            self.draw_instructions()

            # 绘制反馈
            self.draw_feedback()

            # 绘制按钮
            if not self.game_over:
                if not self.round_complete:
                    self.submit_button.draw(self.screen)
                else:
                    self.next_button.draw(self.screen)
            else:
                self.play_again_button.draw(self.screen)
                self.draw_game_over()

            # 更新显示
            pygame.display.flip()
            self.clock.tick(60)

        pygame.quit()
        sys.exit()


class Slider:
    """滑块控件"""

    def __init__(self, x, y, width, height, color, initial_value=128):
        self.rect = pygame.Rect(x, y, width, height)
        self.color = color
        self.value = initial_value
        self.dragging = False

        # 滑块按钮
        self.button_radius = 10
        self.update_button_position()

    def update_button_position(self):
        """更新滑块按钮位置"""
        self.button_x = self.rect.x + (self.value / 255) * self.rect.width

    def handle_event(self, event):
        """处理鼠标事件"""
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = event.pos
            # 检查是否点击在滑块按钮上
            if (self.button_x - self.button_radius <= mouse_x <= self.button_x + self.button_radius and
                    self.rect.y - self.button_radius <= mouse_y <= self.rect.y + self.button_radius):
                self.dragging = True
            # 检查是否点击在滑块条上
            elif self.rect.collidepoint(mouse_x, mouse_y):
                self.dragging = True
                # 直接跳转到点击位置
                relative_x = max(
                    0, min(self.rect.width, mouse_x - self.rect.x))
                self.value = int((relative_x / self.rect.width) * 255)
                self.update_button_position()

        elif event.type == pygame.MOUSEBUTTONUP:
            self.dragging = False

        elif event.type == pygame.MOUSEMOTION and self.dragging:
            mouse_x, _ = event.pos
            relative_x = max(0, min(self.rect.width, mouse_x - self.rect.x))
            self.value = int((relative_x / self.rect.width) * 255)
            self.update_button_position()

        return True

    def draw(self, screen):
        """绘制滑块"""
        # 绘制滑块轨道
        pygame.draw.rect(screen, LIGHT_GRAY, self.rect)
        pygame.draw.rect(screen, DARK_GRAY, self.rect, 2)

        # 绘制填充部分
        fill_width = (self.value / 255) * self.rect.width
        fill_rect = pygame.Rect(self.rect.x, self.rect.y,
                                fill_width, self.rect.height)
        pygame.draw.rect(screen, self.color, fill_rect)

        # 绘制滑块按钮
        pygame.draw.circle(screen, BLACK, (int(self.button_x),
                           self.rect.centery), self.button_radius + 2)
        pygame.draw.circle(screen, self.color, (int(
            self.button_x), self.rect.centery), self.button_radius)

        # 显示数值
        value_text = pygame.font.Font(None, 24).render(
            str(self.value), True, BLACK)
        screen.blit(value_text, (self.rect.right + 10, self.rect.centery - 12))


class Button:
    """按钮控件"""

    def __init__(self, x, y, width, height, text, color, hover_color):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.hover_color = hover_color
        self.is_hovered = False

    def handle_event(self, event):
        """处理鼠标事件"""
        if event.type == pygame.MOUSEMOTION:
            self.is_hovered = self.rect.collidepoint(event.pos)

        if event.type == pygame.MOUSEBUTTONDOWN:
            if self.is_hovered:
                return True
        return False

    def draw(self, screen):
        """绘制按钮"""
        color = self.hover_color if self.is_hovered else self.color
        pygame.draw.rect(screen, color, self.rect)
        pygame.draw.rect(screen, BLACK, self.rect, 3)

        font = pygame.font.Font(None, 32)
        text_surface = font.render(self.text, True, WHITE)
        text_rect = text_surface.get_rect(center=self.rect.center)
        screen.blit(text_surface, text_rect)


if __name__ == "__main__":
    game = ColorMatchingGame()
    game.run()
