import pygame as pg
import asyncio
import sys

#初始化
pg.init()

#主界面的尺寸和底色
screen = pg.display.set_mode((900, 1200))
screen.fill('#ffffdd')

#标题
pg.display.set_caption('◇CATS & FISH◆')

#加载图片素材
img_main_game = pg.image.load('assets/main_game.svg')
img_main_game_end = pg.image.load('assets/main_game_end.svg')
img_prev_page = pg.image.load('assets/prev_page.svg')
img_next_page = pg.image.load('assets/next_page.svg')
img_reset = pg.image.load('assets/reset.svg')
img_start = pg.image.load('assets/start.svg')
img_win = pg.image.load('assets/win.svg')
img_wrong = pg.image.load('assets/wrong.svg')
img_move = pg.image.load('assets/move.svg')
img_eg = pg.image.load('assets/eg.svg')
img_eg_no_cat = pg.image.load('assets/eg_no_cat.svg')
img_eg_no_green = pg.image.load('assets/eg_no_green.svg')
img_eg_no_catfish = pg.image.load('assets/eg_no_catfish.svg')
img_eg_cat_replace_fish = pg.image.load('assets/eg_cat_replace_fish.svg')
img_magnet_used = pg.image.load('assets/magnet_used.svg')
img_magnet_unused = pg.image.load('assets/magnet_unused.svg')
img_magnet_placed = pg.image.load('assets/magnet_placed.svg')
img_magnet_pointed = pg.image.load('assets/magnet_pointed.svg')
dct_img_cat = {}
dct_img_cat['x'] = pg.image.load('assets/cat.svg')
dct_img_cat['x1'] = pg.image.load('assets/cat_half_dotted_1.svg')
dct_img_cat['x2'] = pg.image.load('assets/cat_half_dotted_2.svg')
dct_img_cat['xd'] = pg.image.load('assets/cat_dotted.svg')
dct_img_cat['y'] = pg.transform.flip(dct_img_cat['x'], True, False)
dct_img_cat['y1'] = pg.transform.flip(dct_img_cat['x1'], True, False)
dct_img_cat['y2'] = pg.transform.flip(dct_img_cat['x2'], True, False)
dct_img_cat['yd'] = pg.transform.flip(dct_img_cat['xd'], True, False)

#生成封面
page_cover = pg.Surface((900, 1040))
page_cover.fill('#ffffdd')
page_cover.blit(img_eg_no_green, (210, 360))


#生成教学关页-放置环节
page_tutorial_place = pg.Surface((900, 1040))
page_tutorial_place.fill('#ffffdd')
page_tutorial_place.blit(img_eg, (210, 360))

magnetbar_tutorial = pg.Surface((60 * 2, 60))

#生成教学关页-移动环节
page_tutorial_move = pg.Surface((900, 1040))
page_tutorial_move.fill('#ffffdd')
page_tutorial_move.blit(img_eg, (210, 360))


#生成主关卡页
page_main_game = pg.Surface((900, 1040))
page_main_game.fill('#ffffdd')
page_main_game.blit(img_main_game)

magnetbar_main_game = pg.Surface((60 * 9, 60))

screen.blit(page_cover)

#翻页按钮
MARGIN_X, MARGIN_Y = 40, 40
screen.blit(img_start, (405, 1200-90-MARGIN_Y))

#计算教学关有方块的位置
solid_xyz = []
for i in range(10):
    for j in range(3):
        solid_xyz.append((i, j, -1))
for i in range(8):
    for j in range(6):
        solid_xyz.append((1 + i, 1, j))
solid_xyz.remove((2, 1, 2))
solid_xyz.remove((7, 1, 3))
solid_xyz.append((2, 2, 1))
solid_xyz.append((3, 2, 1))
solid_xyz.append((5, 2, 3))
solid_xyz.append((5, 2, 4))
solid_xyz.append((6, 2, 2))
solid_xyz.append((7, 2, 2))

#计算教学关可放方块的位置
turorial_available_xyz = set()
for i in range(10):
    for j in range(3):
        turorial_available_xyz.add((i, j, 0))
for i in range(8):
    turorial_available_xyz.add((i + 1, 1, 6))
    for j in range(6):
        if (i, j) in ((1, 2), (6, 3)):
            continue
        turorial_available_xyz.add((i + 1, 0, j))
        turorial_available_xyz.add((i + 1, 2, j))
for xyz in solid_xyz:
    turorial_available_xyz.discard(xyz)
turorial_available_uv = set()
for x, y, z in turorial_available_xyz:
    turorial_available_uv.add((555 + y * 30 - x * 30, 585 + x * 10 + y * 10 - z * 40))

#计算主关卡可放方块的位置
available_xyz = set()
test_xyz = set()
for i in range(30):
    for j in range(30):
        if -14 < i - j < 17:
            available_xyz.add((i, j, 0))
for i in range(10):
    available_xyz.add((4, 2, i))
    available_xyz.add((13, 2, i))
    available_xyz.add((28, 27, i))
    available_xyz.add((19, 27, i))
    available_xyz.add((2, 2 + i, 8))
    available_xyz.add((27, 15 + i, 8))
    available_xyz.remove((2, 2 + i, 0))
    available_xyz.remove((27, 15 + i, 0))
    for j in range(8):
        available_xyz.add((5 + j, 1, i))
        available_xyz.add((5 + j, 3, i))
        available_xyz.add((20 + j, 26, i))
        available_xyz.add((20 + j, 28, i))
for i in range(8):
    available_xyz.add((2, 1, i))
    available_xyz.add((2, 12, i))
    available_xyz.add((27, 25, i))
    available_xyz.add((27, 14, i))
    available_xyz.add((5 + i, 2, 10))
    available_xyz.add((20 + i, 27, 10))
    available_xyz.remove((5 + i, 2, 0))
    available_xyz.remove((20 + i, 27, 0))
    for j in range(10):
        available_xyz.add((1, 2 + j, i))
        available_xyz.add((3, 2 + j, i))
        available_xyz.add((26, 15 + j, i))
        available_xyz.add((28, 15 + j, i))
magnet_xyz = [(6, 3, 2), (7, 3, 3), (11, 3, 3), (8, 3, 2), (11, 3, 5), (10, 3, 6),(10, 3, 7), (3, 6, 2), (3, 5, 4), (3, 7, 2), (3, 8, 2), (3, 9, 1), (3, 9, 5), (3, 10, 0), (28, 23, 3), (28, 22, 4), (28, 20, 6), (28, 20, 2), (28, 18, 1), (28, 16, 4), (28, 19, 6), (26, 28, 0), (26, 28, 1), (26, 28, 2), (26, 28, 3), (26, 28, 4), (26, 28, 5), (26, 28, 6)]
for i in magnet_xyz:
    available_xyz.remove(i)
available_xyz.remove((7, 3, 4))
available_xyz.remove((7, 1, 4))
available_xyz.remove((11, 3, 7))
available_xyz.remove((11, 1, 7))
available_xyz.remove((3, 10, 5))
available_xyz.remove((3, 5, 5))
available_xyz.remove((3, 3, 3))
available_xyz.remove((1, 10, 5))
available_xyz.remove((1, 5, 5))
available_xyz.remove((1, 3, 3))
available_xyz.remove((26, 16, 5))
available_xyz.remove((26, 17, 3))
available_xyz.remove((26, 23, 6))
available_xyz.remove((28, 16, 5))
available_xyz.remove((28, 17, 3))
available_xyz.remove((28, 23, 6))
available_xyz.remove((26, 28, 8))
available_xyz.remove((26, 26, 8))
available_xyz.remove((21, 28, 3))
available_xyz.remove((21, 26, 3))
available_uv = set()
for x, y, z in available_xyz:
    available_uv.add((495 + y * 30 - x * 30, 385 + x * 10 + y * 10 - z * 40))


async def main():
    page = 0
    tutorial_placed_magnet = []
    placed_magnet = []
    highlighted_u, highlighted_u = None, None
    cat_x, cat_y, cat_z = 7, 1, 3
    move_dir = 'y'
    flag_eaten = False
    running = True
    while running:
        mouse_u, mouse_v = pg.mouse.get_pos()
        if page == 0:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    running = False
                    break
                if event.type == pg.MOUSEBUTTONDOWN:
                    #判定开始游戏
                    if pg.Rect(405, 1200-90-MARGIN_Y, 90, 90).collidepoint(event.pos):
                        page += 1
                        pg.draw.rect(screen, '#ffffdd', pg.Rect(390, 1085, 120, 60))
                        screen.blit(img_prev_page, (MARGIN_X, 1200-90-MARGIN_Y))
                        screen.blit(img_next_page, (900-90-MARGIN_X, 1200-90-MARGIN_Y))
                        break
            else:
                #page_cover.fill('#ffffdd')
                #page_cover.blit(img_eg_no_green, (210, 360))
                screen.blit(page_cover)
        elif page == 1:
            i = (mouse_u + 3 * mouse_v) // 60 * 60 + 30
            j = (mouse_u - 3 * mouse_v + 30) // 60 * 60
            mouse_ug = (i + j) // 2
            mouse_vg = (i - j) // 6
            if (mouse_ug, mouse_vg) in turorial_available_uv:
                highlighted_u, highlighted_v = mouse_ug, mouse_vg
            else:
                min_distance = 1e4
                for (u, v) in turorial_available_uv:
                    distance = abs(mouse_u - u) + abs(mouse_v - v)
                    if distance < min_distance:
                        min_distance = distance
                        min_uv = (u, v)
                if min_distance < 100:
                    highlighted_u, highlighted_v = min_uv
                else:
                    highlighted_u, highlighted_v = None, None
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    running = False
                    break
                if event.type == pg.MOUSEBUTTONDOWN:
                    #判定左翻页
                    if pg.Rect(MARGIN_X, 1200-90-MARGIN_Y, 90, 90).collidepoint(event.pos):
                        page -= 1
                        pg.draw.rect(screen, '#ffffdd', pg.Rect(0, 1085, 900, 60))
                        screen.blit(img_start, (405, 1200-90-MARGIN_Y))
                        break
                    #判定右翻页
                    if pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90).collidepoint(event.pos):
                        if tutorial_placed_magnet:
                            page += 1
                            pg.draw.rect(screen, '#ffffdd', pg.Rect(390, 1085, 120, 60))
                            if len(tutorial_placed_magnet) == 2:
                                solid_xyz_new = solid_xyz + [(4, 2, 1), (6, 2, 3)]
                            elif (435, 545) in tutorial_placed_magnet:
                                solid_xyz_new = solid_xyz + [(6, 2, 3)]
                            elif (495, 605) in tutorial_placed_magnet:
                                solid_xyz_new = solid_xyz + [(2, 0, 0)]
                            break
                        else:
                            pg.draw.rect(screen, '#ffffdd', pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90))
                            screen.blit(img_wrong, (900-90-MARGIN_X, 1200-90-MARGIN_Y))
                    if not highlighted_u:
                        continue
                    if (highlighted_u, highlighted_v) in ((435, 545), (495, 605)):
                        pg.draw.rect(screen, '#ffffdd', pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90))
                        screen.blit(img_next_page, (900-90-MARGIN_X, 1200-90-MARGIN_Y))
                        if (highlighted_u, highlighted_v) not in tutorial_placed_magnet:
                            tutorial_placed_magnet.append((highlighted_u, highlighted_v))
                        else:
                            tutorial_placed_magnet.remove((highlighted_u, highlighted_v))
            else:
                page_tutorial_place.fill('#ffffdd')
                page_tutorial_place.blit(img_eg, (210, 360))
                if highlighted_u:
                    page_tutorial_place.blit(img_magnet_pointed, (highlighted_u - 45, highlighted_v - 45))
                else:
                    highlighted_u, highlighted_u = None, None
                for u, v in tutorial_placed_magnet:
                    page_tutorial_place.blit(img_magnet_placed, (u - 45, v - 45))
                magnetbar_tutorial.fill('#ffffdd')
                for i in range(2):
                    if i < len(tutorial_placed_magnet):
                        magnetbar_tutorial.blit(img_magnet_used, (60 * i, 0))
                    else:
                        magnetbar_tutorial.blit(img_magnet_unused, (60 * i, 0))
                screen.blit(page_tutorial_place)
                screen.blit(magnetbar_tutorial, (390, 1085))
        elif page == 2:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    running = False
                    break
                if event.type == pg.MOUSEBUTTONDOWN:
                    #判定左翻页
                    if pg.Rect(MARGIN_X, 1200-90-MARGIN_Y, 90, 90).collidepoint(event.pos):
                        page -= 1
                        pg.draw.rect(screen, '#ffffdd', pg.Rect(360, 1085, 180, 60))
                        cat_x, cat_y, cat_z = 7, 1, 3
                        move_dir = 'y'
                        flag_eaten = False
                        break
                    #判定右翻页
                    if pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90).collidepoint(event.pos):
                        if flag_eaten:
                            page += 1
                            break
                        else:
                            pg.draw.rect(screen, '#ffffdd', pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90))
                            screen.blit(img_wrong, (900-90-MARGIN_X, 1200-90-MARGIN_Y))
                    #重置或移动
                    if pg.Rect(430, 1095, 40, 40).collidepoint(event.pos):
                        cat_x, cat_y, cat_z = 7, 1, 3
                        move_dir = 'y'
                        flag_eaten = False
                    elif pg.Rect(375, 1085, 60, 30).collidepoint(event.pos):
                        #左上
                        if cat_y == 0:
                            pass
                        else:
                            if (cat_x, cat_y - 1, cat_z) in solid_xyz_new:
                                if (cat_x, cat_y, cat_z + 1) not in solid_xyz_new and (cat_x, cat_y - 1, cat_z + 1) not in solid_xyz_new:
                                    cat_y -= 1
                                    cat_z += 1
                                    move_dir = 'y'
                                else:
                                    pass
                            else:
                                cat_y -= 1
                                move_dir = 'y'
                                while (cat_x, cat_y, cat_z - 1) not in solid_xyz_new:
                                    cat_z -= 1
                    elif pg.Rect(465, 1085, 60, 30).collidepoint(event.pos):
                        #右上
                        if cat_x == 0:
                            pass
                        else:
                            if (cat_x - 1, cat_y, cat_z) in solid_xyz_new:
                                if (cat_x, cat_y, cat_z + 1) not in solid_xyz_new and (cat_x - 1, cat_y, cat_z + 1) not in solid_xyz_new:
                                    cat_x -= 1
                                    cat_z += 1
                                    move_dir = 'x'
                                else:
                                    pass
                            else:
                                cat_x -= 1
                                move_dir = 'x'
                                while (cat_x, cat_y, cat_z - 1) not in solid_xyz_new:
                                    cat_z -= 1
                    elif pg.Rect(375, 1115, 60, 30).collidepoint(event.pos):
                        #左下
                        if cat_x == 9:
                            pass
                        else:
                            if (cat_x + 1, cat_y, cat_z) in solid_xyz_new:
                                if (cat_x, cat_y, cat_z + 1) not in solid_xyz_new and (cat_x + 1, cat_y, cat_z + 1) not in solid_xyz_new:
                                    cat_x += 1
                                    cat_z += 1
                                    move_dir = 'x'
                                else:
                                    pass
                            else:
                                cat_x += 1
                                move_dir = 'x'
                                while (cat_x, cat_y, cat_z - 1) not in solid_xyz_new:
                                    cat_z -= 1
                    elif pg.Rect(465, 1115, 60, 30).collidepoint(event.pos):
                        #右下
                        if cat_y == 2:
                            pass
                        else:
                            if (cat_x, cat_y + 1, cat_z) in solid_xyz_new:
                                if (cat_x, cat_y, cat_z + 1) not in solid_xyz_new and (cat_x, cat_y + 1, cat_z + 1) not in solid_xyz_new:
                                    cat_y += 1
                                    cat_z += 1
                                    move_dir = 'y'
                                else:
                                    pass
                            else:
                                cat_y += 1
                                move_dir = 'y'
                                while (cat_x, cat_y, cat_z - 1) not in solid_xyz_new:
                                    cat_z -= 1
            else:
                if (cat_x, cat_y, cat_z) == (2, 1, 2):
                    flag_eaten = True
                    pg.draw.rect(screen, '#ffffdd', pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90))
                    screen.blit(img_next_page, (900-90-MARGIN_X, 1200-90-MARGIN_Y))
                page_tutorial_move.fill('#ffffdd')
                if (cat_x, cat_y, cat_z) == (7, 1, 3):
                    page_tutorial_move.blit(img_eg_no_green, (210, 360))
                elif flag_eaten:
                    if (cat_x, cat_y, cat_z) == (2, 1, 2):
                        page_tutorial_move.blit(img_eg_cat_replace_fish, (210, 360))
                    else:
                        page_tutorial_move.blit(img_eg_no_catfish, (210, 360))
                else:
                    page_tutorial_move.blit(img_eg_no_cat, (210, 360))
                for u, v in tutorial_placed_magnet:
                    page_tutorial_move.blit(img_magnet_placed, (u - 45, v - 45))
                cat_u, cat_v = 510 + cat_y * 30 - cat_x * 30, 540 + cat_x * 10 + cat_y * 10 - cat_z * 40
                if cat_y == 0 and cat_x < 8:
                    final_dir = move_dir + 'd'
                elif (cat_x, cat_y, cat_z) == (0, 1, 0):
                    final_dir = 'x1' if move_dir == 'x' else 'y2'
                elif (cat_x, cat_y, cat_z) == (8, 0, 0):
                    final_dir = 'x2' if move_dir == 'x' else 'y1'
                else:
                    final_dir = move_dir
                if (cat_x, cat_y, cat_z) not in ((7, 1, 3), (2, 1, 2)):
                    page_tutorial_move.blit(dct_img_cat[final_dir], (cat_u, cat_v))
                screen.blit(page_tutorial_move)
                pg.draw.rect(screen, '#ffffdd', pg.Rect(360, 1085, 180, 60))
                screen.blit(img_move, (345, 1060))
                screen.blit(img_reset, (405, 1070))
        elif page == 3:
            i = (mouse_u + 3 * mouse_v) // 60 * 60 + 30
            j = (mouse_u - 3 * mouse_v + 30) // 60 * 60
            mouse_ug = (i + j) // 2
            mouse_vg = (i - j) // 6
            #print(mouse_ug, mouse_vg, tuple(available_uv)[1])
            if (mouse_ug, mouse_vg) in available_uv:
                highlighted_u, highlighted_v = mouse_ug, mouse_vg
            else:
                min_distance = 1e4
                for (u, v) in available_uv:
                    distance = abs(mouse_u - u) + abs(mouse_v - v)
                    if distance < min_distance:
                        min_distance = distance
                        min_uv = (u, v)
                if min_distance < 100:
                    highlighted_u, highlighted_v = min_uv
                else:
                    highlighted_u, highlighted_v = None, None
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    running = False
                    break
                if event.type == pg.MOUSEBUTTONDOWN:
                    #判定左翻页
                    if pg.Rect(MARGIN_X, 1200-90-MARGIN_Y, 90, 90).collidepoint(event.pos):
                        page -= 1
                        pg.draw.rect(screen, '#ffffdd', pg.Rect(180, 1085, 540, 60))
                        break
                    #判定右翻页
                    if pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90).collidepoint(event.pos):
                        for uv in ((225, 735), (195, 685), (435, 425), (495, 405), (465, 455), (585, 355), (435, 625), (465, 595), (285, 675)):
                            if uv not in placed_magnet:
                                pg.draw.rect(screen, '#ffffdd', pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90))
                                screen.blit(img_wrong, (900-90-MARGIN_X, 1200-90-MARGIN_Y))
                                break
                        else:
                            page += 1
                            pg.draw.rect(screen, '#ffffdd', pg.Rect(180, 1085, 540, 60))
                            break
                    if not highlighted_u:
                        continue
                    pg.draw.rect(screen, '#ffffdd', pg.Rect(900-90-MARGIN_X, 1200-90-MARGIN_Y, 90, 90))
                    screen.blit(img_next_page, (900-90-MARGIN_X, 1200-90-MARGIN_Y))
                    if (highlighted_u, highlighted_v) not in placed_magnet:
                        if len(placed_magnet) < 9:
                            placed_magnet.append((highlighted_u, highlighted_v))
                    else:
                        placed_magnet.remove((highlighted_u, highlighted_v))
            else:
                page_main_game.fill('#ffffdd')
                page_main_game.blit(img_main_game, (0, 30))
                if highlighted_u:
                    page_main_game.blit(img_magnet_pointed, (highlighted_u - 45, highlighted_v - 45))
                else:
                    highlighted_u, highlighted_u = None, None
                #print(placed_magnet)
                for u, v in placed_magnet:
                    page_main_game.blit(img_magnet_placed, (u - 45, v - 45))
                magnetbar_main_game.fill('#ffffdd')
                for i in range(9):
                    if i < len(placed_magnet):
                        magnetbar_main_game.blit(img_magnet_used, (60 * i, 0))
                    else:
                        magnetbar_main_game.blit(img_magnet_unused, (60 * i, 0))
                screen.blit(magnetbar_main_game, (180, 1085))
                screen.blit(page_main_game)
        elif page == 4:
            screen.fill('#ffffdd')
            screen.blit(img_main_game_end, (0, 30))
            screen.blit(img_win, (405, 1200-90-MARGIN_Y))
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    pg.quit()
                    sys.exit()
        pg.display.flip()
        await asyncio.sleep(0)
    pg.quit()

try:
    asyncio.get_running_loop()
except RuntimeError:
    asyncio.run(main())
else:
    asyncio.create_task(main())