import pygame
import random
import math

# 初始化Pygame
pygame.init()
WIDTH, HEIGHT = 1200, 800
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("易经占卜")
font = pygame.font.SysFont("SimHei", 30)
small_font = pygame.font.SysFont("SimHei", 20)
large_font = pygame.font.SysFont("SimHei", 40)
clock = pygame.time.Clock()

# 颜色定义
COLORS = {
    "background": (40, 40, 40),
    "wood": (200, 200, 200),
    "selected": (255, 0, 0),
    "text": (255, 255, 255),
    "yin": (0, 0, 255),
    "yang": (255, 0, 0),
    "tian": (0, 255, 0),
    "di": (255, 255, 0),
    "ren": (255, 0, 255)
}

# 六十四卦及其卦辞
gua_gua_ci = {
    "乾卦": "元，亨，利，贞。",
    "坤卦": "元亨，利牝马之贞。君子有攸往，先迷后得主。利西南得朋，东北丧朋。安贞吉。",
    "屯卦": "元亨利贞。勿用有攸往，利建侯。",
    "蒙卦": "亨。匪我求童蒙，童蒙求我。初噬告，再三渎，渎则不告。利贞。",
    "需卦": "有孚，光亨，贞吉。利涉大川。",
    "讼卦": "有孚，窒惕，中吉，终凶。利见大人，不利涉大川。",
    "师卦": "贞丈人吉，无咎。",
    "比卦": "吉。原筮，元永贞，无咎。不宁方来，后夫凶。",
    "小畜卦": "亨。密云不雨，自我西郊。",
    "履卦": "履虎尾，不咥人。亨。",
    "泰卦": "小往大来，吉亨。",
    "否卦": "否之匪人，不利君子贞，大往小来。",
    "同人卦": "同人于野，亨。利涉大川，利君子贞。",
    "大有卦": "大有，元亨。",
    "谦卦": "亨。君子有终。",
    "豫卦": "利建侯行师。",
    "随卦": "元亨利贞，无咎。",
    "蛊卦": "元亨，利涉大川。先甲三日，后甲三日。",
    "临卦": "元亨利贞，至于八月有凶。",
    "观卦": "盥而不荐，有孚顒若。",
    "噬嗑卦": "亨，利用狱。",
    "贲卦": "小利有攸往。",
    "剥卦": "不利有攸往。",
    "复卦": "亨。出入无疾，朋来无咎。反复其道，七日来复。利有攸往。",
    "无妄卦": "元亨利贞。其匪正有眚，不利有攸往。",
    "大畜卦": "利贞，不家食吉，利涉大川。",
    "颐卦": "贞吉，观颐，自求口实。",
    "大过卦": "栋桡，利有攸往，亨。",
    "坎卦": "习坎，有孚，维心亨，行有尚。",
    "离卦": "利贞，亨。畜牝牛，吉。",
    "咸卦": "亨，利贞，取女吉。",
    "恒卦": "亨，无咎，利贞，利有攸往。",
    "遯卦": "小利贞。",
    "大壮卦": "利贞。",
    "晋卦": "康侯用锡马蕃庶，昼日三接。",
    "明夷卦": "利艰贞。",
    "家人卦": "利女贞。",
    "睽卦": "小事吉。",
    "蹇卦": "利西南，不利东北。利见大人，贞吉。",
    "解卦": "利西南，无不利。初六，无咎。",
    "损卦": "损，有孚，元吉，无咎，可贞，利有攸往。曷之用，二簋可用享。",
    "益卦": "利有攸往，利涉大川。",
    "夬卦": "扬于王庭，孚号有厉，告自邑，不利即戎，利有攸往。",
    "姤卦": "女壮，勿用取女。",
    "萃卦": "亨。王假有庙，利见大人，亨，利涉大川，王假有庙。",
    "升卦": "元亨，用见大人，勿恤，南征吉。",
    "困卦": "贞大人吉，无咎。有言不信。",
    "井卦": "改邑不改井，无丧无得，往来井井。汔至，亦未繘井，羸其瓶，凶。",
    "革卦": "巳日乃孚，元亨，利贞，悔亡。",
    "鼎卦": "元吉，亨。",
    "震卦": "亨。震来虩虩，笑言哑哑，震惊百里，不丧匕鬯。",
    "艮卦": "艮其背，不获其身，行其庭，不见其人，无咎。",
    "渐卦": "女归吉，利贞。",
    "归妹卦": "征凶，无攸利。",
    "丰卦": "亨，王假之，勿忧，宜日中。",
    "旅卦": "小亨，旅贞吉。",
    "巽卦": "小亨，利有攸往，利见大人。",
    "兑卦": "亨，利贞。",
    "涣卦": "亨。王假有庙，利涉大川，利贞。",
    "节卦": "亨。苦节不可贞。",
    "中孚卦": "豚鱼吉，利涉大川，利贞。",
    "小过卦": "亨，利贞。可小事，不可大事。飞鸟遗之音，不宜上，宜下，大吉。",
    "既济卦": "亨小，利贞，初吉终乱。",
    "未济卦": "亨，小狐汔济，濡其尾，无攸利。"
}


class Stick:
    def __init__(self, x, y, group):
        self.original_x = x
        self.original_y = y
        self.x = x
        self.y = y
        self.group = group
        self.rect = pygame.Rect(x - 5, y - 25, 10, 50)
        self.angle = random.random() * 2 * math.pi
        self.swing_speed = 0.05 + random.random() * 0.02
        self.display_x = x
        self.display_y = y

    def update(self):
        if self.group == "初始":
            self.angle += self.swing_speed
            swing_offset = math.sin(self.angle) * 8
            self.display_x = self.original_x + swing_offset
            self.display_y = self.original_y
        else:
            self.display_x = self.x
            self.display_y = self.y
        self.rect.center = (self.display_x, self.display_y)

    def draw(self):
        color = COLORS["wood"]
        if self.group == "天":
            color = COLORS["tian"]
        elif self.group == "地":
            color = COLORS["di"]
        elif self.group == "人":
            color = COLORS["ren"]

        pygame.draw.rect(screen, color, pygame.Rect(self.display_x - 5, self.display_y - 25, 10, 50))

        # 只有初始状态的木条显示轨迹
        if self.group == "初始":
            trail_length = 5
            for i in range(trail_length):
                alpha = 255 * (1 - i / trail_length)
                offset = math.sin(self.angle - i * 0.1) * 8
                pos_x = self.original_x + offset
                trail_rect = pygame.Rect(pos_x - 5, self.display_y - 25, 10, 50)
                pygame.draw.rect(screen, color + (alpha,), trail_rect)


class DivinationApp:
    def __init__(self):
        self.sticks = []
        self.phase = 0
        self.yao_results = []
        self.current_yao_step = 0
        self.current_yao_index = 0
        self.dragging = False
        self.start_pos = (0, 0)
        self.end_pos = (0, 0)
        self.selection_rect = None
        self.selected_sticks = []
        self.final_results = []
        self.show_final = False
        self.remainder_sticks = []
        self.waiting_for_space = False
        self.gua_names = list(gua_gua_ci.keys())
        self.current_gua = {"本卦": "", "变卦": ""}

        self.initialize_sticks(55)
        self.phase = 1  # 初始化时直接进入选择阶段

    def initialize_sticks(self, count):
        self.sticks = []
        positions = set()
        for i in range(count):
            while True:
                x = random.randint(100, WIDTH - 100)
                y = random.randint(100, HEIGHT - 200)
                if all(math.hypot(x - px, y - py) > 50 for (px, py) in positions):
                    break
            positions.add((x, y))
            new_stick = Stick(x, y, "初始")
            self.sticks.append(new_stick)

    def arrange_sticks(self):
        # 天组放在左上角
        tian_sticks = [s for s in self.sticks if s.group == "天"]
        for i, stick in enumerate(tian_sticks):
            stick.x = 100 + (i % 10) * 20
            stick.y = 100 + (i // 10) * 30
            stick.display_x = stick.x
            stick.display_y = stick.y

        # 地组放在右上角
        di_sticks = [s for s in self.sticks if s.group == "地"]
        for i, stick in enumerate(di_sticks):
            stick.x = WIDTH - 100 - (i % 10) * 20
            stick.y = 100 + (i // 10) * 30
            stick.display_x = stick.x
            stick.display_y = stick.y

        # 人组放在中间
        ren_sticks = [s for s in self.sticks if s.group == "人"]
        for i, stick in enumerate(ren_sticks):
            stick.x = WIDTH // 2
            stick.y = 100 + i * 30
            stick.display_x = stick.x
            stick.display_y = stick.y

    def handle_event(self, event):
        if self.show_final:
            if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                self.__init__()
            return

        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1 and not self.waiting_for_space:
                self.dragging = True
                self.start_pos = event.pos
                self.end_pos = event.pos
                self.selection_rect = pygame.Rect(*self.start_pos, 1, 1)

        elif event.type == pygame.MOUSEMOTION:
            if self.dragging and self.selection_rect and not self.waiting_for_space:
                self.end_pos = event.pos
                self.selection_rect.width = self.end_pos[0] - self.start_pos[0]
                self.selection_rect.height = self.end_pos[1] - self.start_pos[1]

        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1 and not self.waiting_for_space:
                self.dragging = False
                threshold = 5

                if (abs(self.start_pos[0] - self.end_pos[0]) < threshold and
                        abs(self.start_pos[1] - self.end_pos[1]) < threshold):
                    mouse_pos = pygame.mouse.get_pos()
                    self.selected_sticks = [s for s in self.sticks if s.rect.collidepoint(mouse_pos)]
                else:
                    x1 = min(self.start_pos[0], self.end_pos[0])
                    y1 = min(self.start_pos[1], self.end_pos[1])
                    x2 = max(self.start_pos[0], self.end_pos[0])
                    y2 = max(self.start_pos[1], self.end_pos[1])
                    valid_rect = pygame.Rect(x1, y1, x2 - x1, y2 - y1)
                    self.selected_sticks = [s for s in self.sticks if valid_rect.colliderect(s.rect)]

                self.selection_rect = None

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                if self.show_final:
                    self.__init__()
                elif self.waiting_for_space:
                    self.waiting_for_space = False
                    self.proceed_to_next_step()
                elif self.phase == 1 and len(self.selected_sticks) > 0:
                    for s in self.selected_sticks:
                        s.group = "天"
                    for s in self.sticks:
                        if s.group == "初始":
                            s.group = "地"
                    self.arrange_sticks()
                    self.waiting_for_space = True
                    self.phase = 2

    def proceed_to_next_step(self):
        if self.phase == 2:
            di_group = [s for s in self.sticks if s.group == "地"]
            if di_group:
                human = random.choice(di_group)
                human.group = "人"
                self.arrange_sticks()
                self.waiting_for_space = True
                self.phase = 3
            else:
                self.phase = 1
                self.selected_sticks = []
            return

        elif self.phase == 3:
            tian_group = [s for s in self.sticks if s.group == "天"]
            di_group = [s for s in self.sticks if s.group == "地"]
            human_group = [s for s in self.sticks if s.group == "人"]

            tian_remainder = len(tian_group) % 4
            tian_remainder = 4 if tian_remainder == 0 else tian_remainder

            di_remainder = (len(di_group) - 1) % 4
            di_remainder = 4 if di_remainder == 0 else di_remainder

            self.remainder_sticks = tian_group[-tian_remainder:] + di_group[-di_remainder:]

            remaining_sticks = (
                    tian_group[:-tian_remainder] +
                    di_group[:-di_remainder] +
                    human_group
            )

            self.sticks = remaining_sticks
            for s in self.sticks:
                s.group = "初始"

            if self.current_yao_step < 2:
                self.current_yao_step += 1
                self.waiting_for_space = True
                self.phase = 1
                self.initialize_sticks(len(self.sticks))
            else:
                total = len(self.sticks)
                self.yao_results.append(total)
                self.current_yao_step = 0

                if self.current_yao_index < 5:
                    self.initialize_sticks(49)
                    self.waiting_for_space = True
                    self.phase = 1
                    self.current_yao_index += 1
                else:
                    self.process_final_results()
                    self.show_final = True

    def process_final_results(self):
        ben_gua = []
        for num in self.yao_results:
            value = num // 4
            ben_gua.append("---" if value in [7, 9] else "- -")

        bian_gua = []
        for val in self.yao_results:
            original = val // 4
            if original == 6:
                bian_gua.append("---")
            elif original == 9:
                bian_gua.append("- -")
            else:
                bian_gua.append(ben_gua[len(bian_gua)])

        self.final_results = {
            "本卦": ben_gua[::-1],
            "变卦": bian_gua[::-1]
        }

        # 确定卦名
        self.current_gua["本卦"] = random.choice(self.gua_names)
        self.current_gua["变卦"] = random.choice(self.gua_names)

    def update(self):
        for stick in self.sticks:
            stick.update()

    def draw(self):
        if self.show_final:
            # 使用纯色背景
            screen.fill((40, 40, 40))  # 白色背景
            self.draw_hexagrams()
        else:
            # 正常绘制背景和木条
            screen.fill(COLORS["background"])
            for stick in self.sticks:
                stick.draw()

            if self.dragging and self.selection_rect:
                pygame.draw.rect(screen, (0, 255, 0), self.selection_rect, 2)

            for stick in self.selected_sticks:
                pygame.draw.rect(screen, COLORS["selected"], stick.rect, 2)

            # 显示详细引导信息
            guide_texts = [
                "第一步：请框选天木条（左键拖拽或点击）",
                "第二步：按空格键确认分组",
                "第三步：系统自动选择人木条...",
                "第四步：按空格键确认选择",
                "第五步：正在计算余数...",
                "第六步：按空格键继续"
            ]
            text = font.render(guide_texts[self.phase - 1], True, COLORS["text"])
            screen.blit(text, (20, 20))

            progress = f"当前爻：{self.current_yao_index + 1}/6 步骤：{self.current_yao_step + 1}/3"
            text = small_font.render(progress, True, COLORS["text"])
            screen.blit(text, (WIDTH - 350, 20))

            # 显示余数木条
            if self.remainder_sticks:
                text = small_font.render(f"余数木条: {len(self.remainder_sticks)}", True, COLORS["text"])
                screen.blit(text, (WIDTH // 2 - 100, HEIGHT - 100))
                for i, stick in enumerate(self.remainder_sticks):
                    pygame.draw.rect(screen, COLORS["selected"],
                                     pygame.Rect(WIDTH // 2 - 50 + i * 15, HEIGHT - 50, 10, 50))

            if self.waiting_for_space:
                text = font.render("请按空格键继续", True, COLORS["text"])
                screen.blit(text, (WIDTH // 2 - 100, HEIGHT // 2))

            # 添加文化元素
            if self.phase == 1:
                text = small_font.render("《易经》云：观其生，观其动，观其变", True, COLORS["text"])
                screen.blit(text, (WIDTH - 350, 50))

        pygame.display.flip()

    def draw_hexagrams(self):
        # 绘制本卦
        y_pos = 500
        start_x = 300
        for symbol in self.final_results["本卦"]:
            color = COLORS["yin"] if symbol == "- -" else COLORS["yang"]
            if symbol == "- -":
                pygame.draw.line(screen, color, (start_x, y_pos), (start_x + 40, y_pos), 3)
                pygame.draw.line(screen, color, (start_x + 50, y_pos), (start_x + 90, y_pos), 3)
            else:
                pygame.draw.line(screen, color, (start_x, y_pos), (start_x + 90, y_pos), 3)
            y_pos -= 40

        # 绘制变卦
        y_pos = 500
        start_x = 600
        for symbol in self.final_results["变卦"]:
            color = COLORS["yin"] if symbol == "- -" else COLORS["yang"]
            if symbol == "- -":
                pygame.draw.line(screen, color, (start_x, y_pos), (start_x + 40, y_pos), 3)
                pygame.draw.line(screen, color, (start_x + 50, y_pos), (start_x + 90, y_pos), 3)
            else:
                pygame.draw.line(screen, color, (start_x, y_pos), (start_x + 90, y_pos), 3)
            y_pos -= 40

        # 显示卦名
        text = large_font.render(f"本卦：{self.current_gua['本卦']}", True, COLORS["text"])
        screen.blit(text, (300, 550))
        text = large_font.render(f"变卦：{self.current_gua['变卦']}", True, COLORS["text"])
        screen.blit(text, (600, 550))

        # 显示卦辞
        ben_gua_ci = gua_gua_ci.get(self.current_gua["本卦"], "此卦象无卦辞...")
        bian_gua_ci = gua_gua_ci.get(self.current_gua["变卦"], "此卦象无卦辞...")

        text = small_font.render(f"本卦卦辞：{ben_gua_ci}", True, COLORS["text"])
        screen.blit(text, (300, 600))
        text = small_font.render(f"变卦卦辞：{bian_gua_ci}", True, COLORS["text"])
        screen.blit(text, (300, 630))

        # 显示重新开始提示
        text = font.render("按空格键重新开始", True, COLORS["text"])
        screen.blit(text, (WIDTH // 2 - 100, HEIGHT - 50))

        # 添加文化元素
        text = small_font.render("《易经》云：一阴一阳之谓道，继之者善也，成之者性也。", True, COLORS["text"])
        screen.blit(text, (WIDTH // 2 - 300, 20))


app = DivinationApp()
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        app.handle_event(event)

    app.update()
    app.draw()
    clock.tick(60)

pygame.quit()