import { system, EnchantmentType, ItemStack } from "@minecraft/server"



export class SawComponent {
    constructor() {
        this.onTick = this.onTick.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);

        this.tickCpt = 0
        this.REDSTONE_POWER_BLOCKS = [
            { id: "minecraft:redstone_wire", state: "redstone_signal" },
            { id: "minecraft:powered_comparator", state: "minecraft:cardinal_direction" },
            { id: "minecraft:powered_repeater", state: "minecraft:cardinal_direction" },
            { id: "minecraft:redstone_torch", state: "torch_facing_direction" },
            { id: "minecraft:observer", state: "minecraft:facing_direction" },
            { id: "minecraft:lever", state: "open_bit" },
            { id: "minecraft:lever", state: "open_bit" },
            { id: "_button", state: "button_pressed_bit" },
            { id: "_pressure_plate", state: "redstone_signal" },
            { id: "minecraft:redstone_block", state: null },
        ];

        this.MINECRAFT_LOGS = [
            "minecraft:oak_log",
            "minecraft:pale_oak_log",
            "minecraft:spruce_log",
            "minecraft:birch_log",
            "minecraft:jungle_log",
            "minecraft:acacia_log",
            "minecraft:dark_oak_log",
            "minecraft:crimson_stem",
            "minecraft:warped_stem",
            "minecraft:cherry_log",
            "minecraft:mangrove_log",
            "minecraft:oak_wood",
            "minecraft:pale_oak_wood",
            "minecraft:spruce_wood",
            "minecraft:birch_wood",
            "minecraft:jungle_wood",
            "minecraft:acacia_wood",
            "minecraft:dark_oak_wood",
            "minecraft:crimson_hyphae",
            "minecraft:warped_hyphae",
            "minecraft:cherry_wood",
            "minecraft:mangrove_wood",
            "minecraft:stripped_oak_log",
            "minecraft:stripped_pale_oak_log",
            "minecraft:stripped_spruce_log",
            "minecraft:stripped_birch_log",
            "minecraft:stripped_jungle_log",
            "minecraft:stripped_acacia_log",
            "minecraft:stripped_dark_oak_log",
            "minecraft:stripped_crimson_stem",
            "minecraft:stripped_warped_stem",
            "minecraft:stripped_cherry_log",
            "minecraft:stripped_mangrove_log",
            "minecraft:stripped_oak_wood",
            "minecraft:stripped_pale_oak_wood",
            "minecraft:stripped_spruce_wood",
            "minecraft:stripped_birch_wood",
            "minecraft:stripped_jungle_wood",
            "minecraft:stripped_acacia_wood",
            "minecraft:stripped_dark_oak_wood",
            "minecraft:stripped_crimson_hyphae",
            "minecraft:stripped_warped_hyphae",
            "minecraft:stripped_cherry_wood",
            "minecraft:stripped_mangrove_wood"
        ];

        this.MINECRAFT_LEAVES_AMPLITUDE = [
            2,
            5,
            2,
            5,
            5,
            4,
            2,
            2,
            3,
            3,
        ];

        this.MINECRAFT_LEAVES = [
            "minecraft:oak_leaves",
            "minecraft:pale_oak_leaves",
            "minecraft:spruce_leaves",
            "minecraft:birch_leaves",
            "minecraft:jungle_leaves",
            "minecraft:acacia_leaves",
            "minecraft:dark_oak_leaves",
            "minecraft:mangrove_leaves",
            "minecraft:azalea_leaves",
            "minecraft:flowering_azalea_leaves",
            "minecraft:cherry_leaves"
        ];

        this.SAW_MODE_TEXT = [
            "[1/3] §bNormal Mode§r",
            "[2/3] §bLeaves Mode§r",
            "[3/3] §bStrip Mode§r",
        ]
    }

    onPlayerInteract(e) {
        const block = e.block;
        const player = e.player;
        let selectedSlot = player.selectedSlotIndex;
        let handItem = player.getComponent("inventory").container.getItem(selectedSlot);

        if (handItem?.typeId.includes('enchanted_book')) {
            const enchantment = handItem.getComponent("enchantable");
            if (enchantment.hasEnchantment(new EnchantmentType("silk_touch"))) {
                block.setPermutation(block.permutation.withState(`pb_red:silk_touch`, true));
                player.getComponent("inventory").container.setItem(selectedSlot, null);
                player.runCommand(`tellraw @s {"rawtext":[{"text":" - Upgraded Saw with §dSilk Touch§r. It will now drop actual leaves in §bLeaves Mode"}]}`)
                block.dimension.runCommand(`playsound random.orb @a ${block.location.x} ${block.location.y} ${block.location.z}`)
                this.tickCpt = 1
                return;
            }
        } else if (handItem?.typeId == "pb_red:redstone_wrench") {
            const saw_mode = block.permutation.getState(`pb_red:saw_mode`)
            if (saw_mode > 1) {
                block.setPermutation(block.permutation.withState(`pb_red:saw_mode`, 0))
            } else {
                block.setPermutation(block.permutation.withState(`pb_red:saw_mode`, saw_mode + 1))
            }
            player.runCommand(`tellraw @s {"rawtext":[{"text":"${this.SAW_MODE_TEXT[block.permutation.getState(`pb_red:saw_mode`)]}"}]}`)
            block.dimension.runCommand(`playsound random.click @a ${block.location.x} ${block.location.y} ${block.location.z}`)

        }
    }

    getOppositeDirection(direction) {
        switch (direction) {
            case 'north':
                return 'south';
            case 'south':
                return 'north';
            case 'east':
                return 'west';
            case 'west':
                return 'east';
            case 'up':
                return 'down';
            case 'down':
                return 'up';
        }
    }

    getFrontBlock(direction, block) {
        switch (direction) {
            case 'north':
                return block.north();
            case 'south':
                return block.south();
            case 'east':
                return block.east();
            case 'west':
                return block.west();
            case 'up':
                return block.above();
            case 'down':
                return block.below();
        }
    }

    breakLogAndAdjacent(block, saw) {
        const logsToCheck = [block];
        const leavesAmplitude = (block.typeId.includes("wood") || block.typeId.includes("stripped")) ? 0 : this.MINECRAFT_LEAVES_AMPLITUDE[this.MINECRAFT_LOGS.indexOf(block.typeId)]

        while (logsToCheck.length > 0) {
            const saw_mode = saw.permutation.getState(`pb_red:saw_mode`)
            const currentBlock = logsToCheck.pop();
            if (this.MINECRAFT_LOGS.includes(currentBlock.typeId) || (this.MINECRAFT_LEAVES.includes(currentBlock.typeId) && saw_mode == 1)) {
                if (this.MINECRAFT_LOGS.indexOf(currentBlock.typeId) <= 19 && saw_mode == 2) {
                    currentBlock.dimension.spawnItem(new ItemStack(`minecraft:stripped_${currentBlock.typeId.replace("minecraft:", "")}`, 1), currentBlock.location)
                    currentBlock.dimension.runCommand(`setblock ${currentBlock.location.x} ${currentBlock.location.y} ${currentBlock.location.z} air`)
                }
                else if (this.MINECRAFT_LEAVES.includes(currentBlock.typeId) && saw_mode == 1 && saw.permutation.getState(`pb_red:silk_touch`) == true) {
                    currentBlock.dimension.spawnItem(new ItemStack(currentBlock.typeId, 1), currentBlock.location)
                    currentBlock.dimension.runCommand(`setblock ${currentBlock.location.x} ${currentBlock.location.y} ${currentBlock.location.z} air`)
                } else {
                    currentBlock.dimension.runCommand(`setblock ${currentBlock.location.x} ${currentBlock.location.y} ${currentBlock.location.z} air destroy`)
                }


                const north = currentBlock.north();
                const east = currentBlock.east();
                const south = currentBlock.south();
                const west = currentBlock.west();
                const above = currentBlock.above();
                const below = currentBlock.below();

                const adjacentBlocks = [north, east, south, west, above, below];
                for (const adjacentBlock of adjacentBlocks) {
                    if (!adjacentBlock) return
                    if ((this.MINECRAFT_LOGS.includes(adjacentBlock.typeId) || (this.MINECRAFT_LEAVES.includes(adjacentBlock.typeId) && saw_mode == 1)) && adjacentBlock.location.y >= saw.location.y) {
                        if (saw_mode !== 1) {
                            logsToCheck.push(adjacentBlock);
                        } else {
                            if (this.isCoordinateInRectangle(saw.location, adjacentBlock.location, leavesAmplitude)) {
                                logsToCheck.push(adjacentBlock);
                            } else if (this.isCoordinateInRectangle(saw.location, adjacentBlock.location, leavesAmplitude + 2)) {
                                if (Math.random() > 0.6)
                                    logsToCheck.push(adjacentBlock);
                            }
                        }
                    }
                }
            }
        }
    }

    isCoordinateInRectangle(center, coord, halfSize) {
        const minX = center.x - halfSize;
        const maxX = center.x + halfSize;
        const minZ = center.z - halfSize;
        const maxZ = center.z + halfSize;

        return (coord.x >= minX && coord.x <= maxX) && (coord.z >= minZ && coord.z <= maxZ);
    }

    onTick(e) {
        const block = e.block;
        let direction = this.getOppositeDirection(block.permutation.getState('minecraft:facing_direction'));
        const north = block.north();
        const east = block.east();
        const south = block.south();
        const west = block.west();
        const above = block.above();
        const below = block.below();

        const adjacentBlocks = [north, east, south, west, above, below];
        const directionList = ["north", "east", "south", "west", "up", "down"];
        let hasRedstonePower = this.hasRedstonePower(adjacentBlocks, directionList);

        if (!hasRedstonePower) {
            try {
                block.setPermutation(block.permutation.withState('pb_red:powered', false));
            } catch { }
            return;
        }
        try {
            block.setPermutation(block.permutation.withState('pb_red:powered', true));
            this.tickCpt++
            if (this.tickCpt % 9 == 0) {
                block.dimension.runCommand(`playsound pb_red.saw_loop @a ${block.location.x} ${block.location.y} ${block.location.z} 0.2`)
            }
        } catch {

        }

        let frontBlock = this.getFrontBlock(direction, block);
        if (!frontBlock) return
        if (this.MINECRAFT_LOGS.includes(frontBlock.typeId)) {
            system.runTimeout(() => {
                try {
                    this.breakLogAndAdjacent(frontBlock, block);
                } catch { }
            }, 20)
        }
    }

    hasRedstonePower(adjacentBlocks, directionList) {

        return adjacentBlocks.some((adjacentBlock, index) => {
            if (!adjacentBlock) return false;

            const redstoneBlock = this.REDSTONE_POWER_BLOCKS.find(({ id }) => adjacentBlock.typeId.includes(id));
            if (!redstoneBlock) return false;

            const { id, state } = redstoneBlock;
            if (id === "minecraft:redstone_block") return true;

            if (id === "minecraft:redstone_wire") {
                let redstonePowerState = adjacentBlock.permutation.getState(state);
                return redstonePowerState > 0;
            }

            if (id === "minecraft:powered_comparator" || id === "minecraft:powered_repeater") {
                return adjacentBlock.permutation.getState(state) === directionList[index];
            }

            if (id === "minecraft:redstone_torch") {
                return adjacentBlock.permutation.getState(state) !== this.getOppositeDirection(directionList[index]) && index !== 4;
            }

            if (id === "minecraft:observer") {
                return adjacentBlock.permutation.getState(state) == directionList[index] && adjacentBlock.permutation.getState("powered_bit") == true;
            }

            if (id === "minecraft:lever") {
                return adjacentBlock.permutation.getState(state) == true;
            }

            if (id === "_button") {
                return adjacentBlock.permutation.getState(state) == true;
            }

            if (id === "_pressure_plate") {
                return adjacentBlock.permutation.getState(state) > 0;
            }

            return false;
        });
    }
}