import * as server from "@minecraft/server";

//interact検知（オリジナルブロック）
server.world.beforeEvents.worldInitialize.subscribe((initEvent) => {
    initEvent.blockComponentRegistry.registerCustomComponent("push:interact", {
        onPlayerInteract: (e) => {
        }
    });
    /////////////////
    initEvent.blockComponentRegistry.registerCustomComponent("pull:interact", {
        onPlayerInteract: (e) => {
        }
    });
    /////////////////
    // GOLEM
    /////////////////
    initEvent.blockComponentRegistry.registerCustomComponent("golem:interact", {
        onPlayerInteract: (e) => {
            const player = e.player;
            const block = e.block;
            const face = e.face;

            const x = block.x;
            const y = block.y;
            const z = block.z;

            //移動よう
            let action_case = 0;
            let golem_typeid = block.type.id;
            let gos = { x: 0, y: 0, z: 0 };
            let golem_xyz = { x: x, y: y, z: z };
            let push_typeid = "";
            let push_xyz = { x: 0, y: 0, z: 0 };
            let floor_xyz = { x: 0, y: 0, z: 0 };
            let foot_xyz = { x: 0, y: 0, z: 0 };
            const e_color = block.type.id.slice(6).split("_")[0];
            let error_move_ms = "その方向にはゴーレムを移動できない";


            //接触処理
            switch (face) {
                case "Down":
                    action_case = 0;
                    error_move_ms = "下面からゴーレムを操作できない";
                    break;
                case "Up":
                    const player_rote_y = player.getRotation().y;
                    if (player_rote_y > 135) {
                        gos = { x: 0, y: 0, z: -1 }
                        action_case = judge_move(block, gos, "north");
                        golem_typeid = "block:" + e_color + "_golem_north"
                    } else if (player_rote_y > 45) {
                        gos = { x: -1, y: 0, z: 0 }
                        action_case = judge_move(block, gos, "west");
                        golem_typeid = "block:" + e_color + "_golem_west"
                    } else if (player_rote_y > -45) {
                        gos = { x: 0, y: 0, z: 1 }
                        action_case = judge_move(block, gos, "south");
                        golem_typeid = "block:" + e_color + "_golem_south"
                    } else if (player_rote_y > -135) {
                        gos = { x: 1, y: 0, z: 0 }
                        action_case = judge_move(block, gos, "east");
                        golem_typeid = "block:" + e_color + "_golem_east"
                    } else {
                        gos = { x: 0, y: 0, z: -1 }
                        action_case = judge_move(block, gos, "north");
                        golem_typeid = "block:" + e_color + "_golem_north"
                    }
                    break;
                case "North":
                    gos = { x: 0, y: 0, z: 1 }
                    action_case = judge_move(block, gos, "south");
                    golem_typeid = "block:" + e_color + "_golem_south"
                    break;
                case "West":
                    gos = { x: 1, y: 0, z: 0 }
                    action_case = judge_move(block, gos, "east");
                    golem_typeid = "block:" + e_color + "_golem_east"
                    break;
                case "South":
                    gos = { x: 0, y: 0, z: -1 }
                    action_case = judge_move(block, gos, "north");
                    golem_typeid = "block:" + e_color + "_golem_north"
                    break;
                case "East":
                    gos = { x: -1, y: 0, z: 0 }
                    action_case = judge_move(block, gos, "west");
                    golem_typeid = "block:" + e_color + "_golem_west"
                    break;
                default:
                    break;
            }

            golem_xyz = { x: x + gos.x, y: y, z: z + gos.z };
            push_typeid = block.offset(gos).type.id;
            push_xyz = { x: x + (gos.x * 2), y: y, z: z + (gos.z * 2) };
            floor_xyz = { x: x + gos.x, y: y - 1, z: z + gos.z };
            foot_xyz = { x: x, y: y - 1, z: z };
            const e_color_powder = block.offset(gos).type.id;

            // 移動処理
            switch (action_case) {
                case -1: // 移動不可
                    player.onScreenDisplay.setActionBar("その色のゴーレムは侵入禁止だ");
                    player.playSound("note.bass");
                    break;
                case 0: // 移動不可
                    player.onScreenDisplay.setActionBar(error_move_ms);
                    player.playSound("note.bass");
                    break;
                case 1:// 箱押し可能
                    block.dimension.setBlockType({ x: x, y: y, z: z }, "minecraft:air");
                    block.dimension.setBlockType(golem_xyz, golem_typeid);
                    block.dimension.setBlockType(push_xyz, push_typeid);


                    block.dimension.spawnParticle("part:push", center_vector(golem_xyz));
                    block.dimension.spawnParticle("part:push", center_vector(push_xyz));

                    player.playSound("block.grindstone.use", {
                        location: golem_xyz,
                        pitch: 1.0,
                        volume: 1.0,
                    });

                    break;
                case 2:// 移動可能
                    block.dimension.setBlockType({ x: x, y: y, z: z }, "minecraft:air");
                    block.dimension.setBlockType(golem_xyz, golem_typeid);

                    block.dimension.spawnParticle("part:push", center_vector(golem_xyz));
                    player.playSound("block.grindstone.use", {
                        location: golem_xyz,
                        pitch: 1.0,
                        volume: 1.0,
                    });
                    break;
                default:
                    break;
            }

            //特殊処理
            if (action_case >= 1) {
                switch (e_color) {
                    case "pink"://可視化
                        const invert_block_a = block.offset({ x: 0, y: - 2, z: 0 }).type.id;
                        if (invert_block_a == "minecraft:sea_lantern") {
                            player.playSound("block.enchanting_table.use", {
                                location: golem_xyz,
                                pitch: 1.0,
                                volume: 1.0,
                            });
                            const s_xyz = `${golem_xyz.x} ${golem_xyz.y} ${golem_xyz.z}`
                            player.runCommand("execute positioned 22 15 69 run fill ~-6 ~-1 ~-6 ~6 ~-1 ~6 block:invert_5 replace block:invert_4");
                            player.runCommand("execute positioned " + String(`${s_xyz}`) + " run fill ~-3 ~-1 ~-3 ~3 ~1 ~3 block:invert_4 replace block:invert_5");
                        }

                        break;
                    case "yellow": //消える（移動前）
                        const invert_offset_y = { x: floor_xyz.x - x, y: - 1, z: floor_xyz.z - z };
                        const invert_block_y = block.offset(invert_offset_y).type.id;
                        // const invert_block_y = block.offset({ x: 0, y: - 1, z: 0 }).type.id;
                        player.runCommand("execute if score golem_2 b matches 0 run function golem_check/ex/2fill");
                        if (invert_block_y == "block:invert_3") {
                            block.dimension.setBlockType(floor_xyz, "block:invert_1");
                            // block.dimension.setBlockType(foot_xyz, "block:invert_1");
                            player.playSound("block.enchanting_table.use", {
                                location: golem_xyz,
                                pitch: 1.0,
                                volume: 1.0,
                            });
                        }
                        player.runCommand("execute if score golem_2 b matches 0 run function golem_check/ex/2ok");
                        break;
                    case "purple"://反転（移動先）
                        const invert_offset_p = { x: floor_xyz.x - x, y: - 1, z: floor_xyz.z - z };
                        const invert_block_p = block.offset(invert_offset_p).type.id;
                        if (invert_block_p == "block:invert_1") {
                            block.dimension.setBlockType(floor_xyz, "block:invert_2");
                            player.playSound("block.enchanting_table.use", {
                                location: golem_xyz,
                                pitch: 1.0,
                                volume: 1.0,
                            });
                        } else if (invert_block_p == "block:invert_2") {
                            block.dimension.setBlockType(floor_xyz, "block:invert_1");
                            player.playSound("block.enchanting_table.use", {
                                location: golem_xyz,
                                pitch: 1.0,
                                volume: 1.0,
                            });
                            player.runCommand("execute if score golem_6 b matches 0 run function golem_check/ex/6ng");
                        }
                        player.runCommand("execute if score golem_6 b matches 0 run function golem_check/ex/6ok");
                        break;
                    case "lime":
                        player.runCommand("function golem_check/ex/4ng");
                        break
                    default:
                        break;
                }
            }

            if (action_case >= 1) {
                const golem_xyz_s = `${golem_xyz.x} ${golem_xyz.y} ${golem_xyz.z} ${e_color}`;
                switch (golem_xyz_s) {
                    //チュートリアル
                    case "115 11 42 cyan":
                        player.runCommand("execute if score golem_phase b matches ..1 run function golem_check/tutorial/01");
                        player.runCommand("execute if score golem_phase b matches 3.. run function golem_check/tutorial/11");
                        break;
                    case "105 11 42 cyan":
                        player.runCommand("execute if score golem_phase b matches ..1 run function golem_check/tutorial/02");
                        player.runCommand("execute if score golem_phase b matches 3.. run function golem_check/tutorial/12");
                        break;
                    case "95 11 42 cyan":
                        player.runCommand("execute if score golem_phase b matches ..1 run function golem_check/tutorial/03");
                        player.runCommand("execute if score golem_phase b matches 3.. run function golem_check/tutorial/13");
                        break;
                    //first
                    case "85 11 42 cyan":
                        player.runCommand("execute if score golem_0 b matches 0 run function golem_check/first/0");
                        break;
                    case "61 11 42 red":
                        player.runCommand("execute if score golem_1 b matches 0 run function golem_check/first/1");
                        break;
                    case "58 15 18 yellow":
                        player.runCommand("execute if score golem_2 b matches 0 run function golem_check/first/2");
                        break;
                    case "26 15 19 orange":
                        player.runCommand("execute if score golem_3 b matches 0 run function golem_check/first/3");
                        break;
                    case "19 14 38 lime":
                        player.runCommand("execute if score golem_4 b matches 0 run function golem_check/first/4");
                        break;
                    case "22 15 62 pink":
                        player.runCommand("execute if score golem_5 b matches 0 run function golem_check/first/5");
                        break;
                    case "54 15 61 purple":
                        player.runCommand("execute if score golem_6 b matches 0 run function golem_check/first/6");
                        break;
                    //second
                    case "46 11 40 red":
                        player.runCommand("execute if score golem_phase b matches ..2 run function golem_check/second/1");
                        break;
                    case "47 15 37 yellow":
                        player.runCommand("execute if score golem_phase b matches ..2 run function golem_check/second/2");
                        break;
                    case "33 15 37 orange":
                        player.runCommand("execute if score golem_phase b matches ..2 run function golem_check/second/3");
                        break;
                    case "34 14 40 lime":
                        player.runCommand("execute if score golem_phase b matches ..2 run function golem_check/second/4");
                        break;
                    case "33 15 43 pink":
                        player.runCommand("execute if score golem_phase b matches ..2 run function golem_check/second/5");
                        break;
                    case "47 15 43 purple":
                        player.runCommand("execute if score golem_phase b matches ..2 run function golem_check/second/6");
                        break;
                    //third
                    // case "120 11 42 cyan": 
                    //     player.runCommand("execute if score golem_phase b matches 3 run function golem_check/third/0");
                    //     break;
                    // case "74 11 42 red":
                    //     player.runCommand("execute if score golem_phase b matches 3 run function golem_check/third/1");
                    //     break;
                    // case "58 15 5 yellow":
                    //     player.runCommand("execute if score golem_phase b matches 3 run function golem_check/third/2");
                    //     break;
                    // case "26 15 6 orange":
                    //     player.runCommand("execute if score golem_phase b matches 3 run function golem_check/third/3");
                    //     break;
                    // case "6 14 38 lime":
                    //     player.runCommand("execute if score golem_phase b matches 3 run function golem_check/third/4");
                    //     break;
                    // case "22 15 75 pink":
                    //     player.runCommand("execute if score golem_phase b matches 3 run function golem_check/third/5");
                    //     break;
                    // case "54 15 74 purple":
                    //     player.runCommand("execute if score golem_phase b matches 3 run function golem_check/third/6");
                    //     break;

                    // sleep
                    case "120 11 42 cyan":
                        player.runCommand("execute if score golem_0 b matches 5.. run function golem_sleep/sleep/0");
                        break;
                    case "74 11 42 red":
                        player.runCommand("execute if score golem_1 b matches 5.. run function golem_sleep/sleep/1");
                        break;
                    case "58 15 5 yellow":
                        player.runCommand("execute if score golem_2 b matches 5.. run function golem_sleep/sleep/2");
                        break;
                    case "26 15 6 orange":
                        player.runCommand("execute if score golem_3 b matches 5.. run function golem_sleep/sleep/3");
                        break;
                    case "6 14 38 lime":
                        player.runCommand("execute if score golem_4 b matches 5.. run function golem_sleep/sleep/4");
                        break;
                    case "22 15 75 pink":
                        player.runCommand("execute if score golem_5 b matches 5.. run function golem_sleep/sleep/5");
                        break;
                    case "54 15 74 purple":
                        player.runCommand("execute if score golem_6 b matches 5.. run function golem_sleep/sleep/6");
                        break;
                    default:
                        //third
                        //sleep
                        player.runCommand("execute if score golem_phase b matches 3.. run function golem_check/third/check");
                        player.runCommand("execute if score golem_phase b matches 3.. run schedule delay add golem_check/powder/check 20t append");
                        break;
                }
            }
        }
    });
});

export function judge_move(block, gos, face) {
    let a1 = gos; // 前
    let b1 = { x: gos.x, y: gos.y - 1, z: gos.z }; //前下
    let c1 = { x: gos.x, y: gos.y + 1, z: gos.z }; // 前上
    let a2 = { x: gos.x * 2, y: gos.y, z: gos.z * 2 }; //２前

    //一方通行
    let can_movable = true;
    if (block.offset({ x: 0, y: -1, z: 0 }).type.id.includes(face)) {
        can_movable = true;
    } else if (block.offset({ x: 0, y: -1, z: 0 }).type.id.includes("block:movable")) {
        can_movable = false;
    } else {
        can_movable = true;
    }

    //移動　前=air 前下"=air,!=golem
    let can_move = (block.offset(a1).type.id == "minecraft:air") && (block.offset(b1).type.id != "minecraft:air") && (block.offset(b1).type.id.includes("golem") == false);

    //箱押し　前=powder 前2=air 前上!=golem 前下"!=golem
    let can_push = (block.offset(a1).type.id.includes("concrete_powder")) && (block.offset(a2).type.id == "minecraft:air") && (block.offset(c1).type.id == "minecraft:air") && (block.offset(b1).type.id.includes("golem") == false);

    //侵入禁止
    const e_color = block.type.id.slice(6).split("_")[0];
    let is_not_allowed_purple = e_color != "purple" && (block.offset(b1).type.id == "minecraft:purple_wool");
    let is_not_allowed_yellow = e_color != "yellow" && (block.offset(b1).type.id == "minecraft:yellow_wool");
    let is_not_allowed_orange = e_color != "orange" && (block.offset(b1).type.id == "minecraft:orange_wool");
    let is_not_allowed_pink = e_color != "pink" && (block.offset(b1).type.id == "minecraft:pink_wool");

    let action_case = 0;
    if (is_not_allowed_purple || is_not_allowed_yellow || is_not_allowed_pink || is_not_allowed_orange) {
        action_case = -1;
    } else if (!can_movable) {
        action_case = 0; //移動不可
    } else if (can_push) {
        action_case = 1; //箱押し可能
    } else if (can_move) {
        action_case = 2; //移動可能
    }
    return action_case;

};

export function center_vector(v) {
    return { x: v.x + 0.5, y: v.y, z: v.z + 0.5 };
}
