import { world, system, BlockPermutation, ItemStack } from '@minecraft/server'

world.afterEvents.playerBreakBlock.subscribe(({ player, block }) => {
    if(block.below().hasTag("isFallingBlock")) {
        for(const fallingBlock of fallingBlocks) {
            checkBlocksToFall(block.below(), `${fallingBlock.identifier}`, `${fallingBlock.entity}`);
        }
    }
});

world.afterEvents.pistonActivate.subscribe(({ piston, block }) => {
    const locations = piston.getAttachedBlocksLocations();
    for(const loc of locations) {
        const aBlock = block.dimension.getBlock({ x: loc.x, y: loc.y, z: loc.z });
        system.runTimeout(() => {
            fallingBlocks.forEach((fallingBlock) => {
                checkBlocksAroundToFall(aBlock, `${fallingBlock.identifier}`, `${fallingBlock.entity}`);
            });
        },7);
    }
    const facingDirection = piston.block.permutation.getState("facing_direction");
    system.runTimeout(() => {
        if(facingDirection == 1) {
            const fBlock = piston.block.dimension.getBlock(piston.block.offset({ x: 0, y: 1, z: 0 }));
            fallingBlocks.forEach((fallingBlock) => {
                checkBlocksAroundToFall(fBlock, `${fallingBlock.identifier}`, `${fallingBlock.entity}`);
            });
        }
    },7);
});

system.afterEvents.scriptEventReceive.subscribe(({id, message, sourceEntity: entity}) => {
    if(id === 'id:turnIntoBlock') {
        //if(!entity.isValid()) return;
        const block = entity.dimension.getBlock(entity.location);
        fallingBlocks.forEach((fallingBlock) => {
            if(entity.typeId !== `${fallingBlock.entity}`) return;
            let item = undefined
            if(fallingBlock.item !== undefined && `${fallingBlock.item}` !== "minecraft:air") {
                item = new ItemStack(`${fallingBlock.item}`);
            }
            if(blockList.includes(block?.typeId) || block.hasTag("minecraft:crop")) {
                block.setPermutation(BlockPermutation.resolve(`${fallingBlock.identifier}`));
                if(fallingBlock.sound !== "none" && fallingBlock.sound !== undefined) {
                    const name = fallingBlock.sound.name === undefined ? `${fallingBlock.sound}` : `${fallingBlock.sound.name}`;
                    const volume = fallingBlock.sound.volume === undefined ? 100 : `${fallingBlock.sound.volume}`;
                    const pitch = fallingBlock.sound.pitch === undefined ? 1 : `${fallingBlock.sound.pitch}`;
                    entity.runCommand(`playsound ${name} @a ~~~ ${volume} ${pitch}`);
                }
                entity.remove();
            } else {
                dropFallingEntity(entity, item);
            }
        });
    }
});

world.afterEvents.explosion.subscribe((data) => {
    data.getImpactedBlocks().forEach((block) => {
        fallingBlocks.forEach((fallingBlock) => {
            system.run(() => {
                checkBlocksAroundToFall(block, `${fallingBlock.identifier}`, `${fallingBlock.entity}`);
            });
        });
    })
})

export function checkBlocksToFall(block, fallingBlock, fallingEntity) {
    if(!block.hasTag("isFallingBlock") || !blockList.includes(block.below().typeId)) return;
    if(block.typeId === `${fallingBlock}`) {
        if(block.below().hasTag("isFallingBlock")) {
            fallingBlocks.forEach((fallingBlockAbove) => {
                forceBlocksToFall(block.below(), `${fallingBlockAbove.identifier}`, `${fallingBlockAbove.entity}`);
            });
        }
        fallingBlocks.forEach((fBlock) => {
            if(fBlock.identifier !== `${fallingBlock}`) return;
            block.setPermutation(BlockPermutation.resolve("minecraft:air"));
            block.dimension.spawnEntity(`${fallingEntity}`, { x: block.location.x + 0.5, y: block.location.y, z: block.location.z + 0.5 });
            if (block.north().hasTag("candle"))block.north().dimension.runCommand(`setblock ${block.north().x} ${block.north().y} ${block.north().z} air destroy`)
            if (block.south().hasTag("candle"))block.south().dimension.runCommand(`setblock ${block.south().x} ${block.south().y} ${block.south().z} air destroy`)
            if (block.east().hasTag("candle"))block.east().dimension.runCommand(`setblock ${block.east().x} ${block.east().y} ${block.east().z} air destroy`)
            if (block.west().hasTag("candle"))block.west().dimension.runCommand(`setblock ${block.west().x} ${block.west().y} ${block.west().z} air destroy`)
        });
    }
}

export function forceBlocksToFall(block, fallingBlock, fallingEntity) {
    system.runTimeout(() => {
        if(block.typeId !== `${fallingBlock}`) return;
        if(block.below().hasTag("isFallingBlock")) {
            for(const fallingBlockAbove of fallingBlocks)
            forceBlocksToFall(block.below(), `${fallingBlockAbove.identifier}`, `${fallingBlockAbove.entity}`);
        }
        fallingBlocks.forEach((fBlock) => {
            if(fBlock.identifier !== `${fallingBlock}`) return;
            if(fBlock.type !== "layers") {
                block.setPermutation(BlockPermutation.resolve("minecraft:air"));
                block.dimension.spawnEntity(`${fallingEntity}`, { x: block.location.x + 0.5, y: block.location.y, z: block.location.z + 0.5 });
            } else {
                const layerState = block.permutation.getState(`${fBlock.layerState}`);
                block.setPermutation(BlockPermutation.resolve("minecraft:air"));
                block.dimension.spawnEntity(`${fallingEntity}`, { x: block.location.x + 0.5, y: block.location.y, z: block.location.z + 0.5 }).setProperty(`${fBlock.layerProperty}`, layerState);
            }
        });
    },5);
}

export function dropFallingEntity(entity, item) {
    fallingBlocks.forEach((fallingBlock) => {
        if(entity.typeId !== `${fallingBlock.entity}`) return;
        if(item !== undefined) {
            entity.dimension.spawnItem(item, { x: entity.location.x, y: entity.location.y + 0.5, z: entity.location.z });
        }
        if(fallingBlock.sound !== "none" && fallingBlock.sound !== undefined) {
            const name = fallingBlock.sound.name === undefined ? `${fallingBlock.sound}` : `${fallingBlock.sound.name}`;
            const volume = fallingBlock.sound.volume === undefined ? 10 : `${fallingBlock.sound.volume}`;
            const pitch = fallingBlock.sound.pitch === undefined ? 1 : `${fallingBlock.sound.pitch}`;
            entity.runCommand(`playsound ${name} @a ~~~ ${volume} ${pitch}`);
        }
        entity.remove();
    });
}

export function checkBlocksAroundToFall(block, fallingBlock, fallingEntity) {
    checkBlocksToFall(block.below(), `${fallingBlock}`, `${fallingEntity}`);
    checkBlocksToFall(block.north(), `${fallingBlock}`, `${fallingEntity}`);
    checkBlocksToFall(block.south(), `${fallingBlock}`, `${fallingEntity}`);
    checkBlocksToFall(block.east(), `${fallingBlock}`, `${fallingEntity}`);
    checkBlocksToFall(block.west(), `${fallingBlock}`, `${fallingEntity}`);
}


export const fallingBlocks = [
    {
        identifier: "rustic:chandelier_iron",
        entity: "rustic:chandelier_entity",
        item: "rustic:chandelier_iron",
        sound: {
            name: "random.anvil_land",
            volume: 100,
            pitch: 1
        }
    },
    {
        identifier: "rustic:chandelier_gold",
        entity: "rustic:chandelier_entity_gold",
        item: "rustic:chandelier_gold",
        sound: {
            name: "random.anvil_land",
            volume: 100,
            pitch: 1
        }
    },
    {
        identifier: "rustic:chandelier_copper",
        entity: "rustic:chandelier_entity_copper",
        item: "rustic:chandelier_copper",
        sound: {
            name: "random.anvil_land",
            volume: 100,
            pitch: 1
        }
    },
    {
        identifier: "rustic:chandelier_copper_exposed",
        entity: "rustic:chandelier_entity_copper_exposed",
        item: "rustic:chandelier_copper_exposed",
        sound: {
            name: "random.anvil_land",
            volume: 100,
            pitch: 1
        }
    },
    {
        identifier: "rustic:chandelier_copper_weathered",
        entity: "rustic:chandelier_entity_copper_weathered",
        item: "rustic:chandelier_copper_weathered",
        sound: {
            name: "random.anvil_land",
            volume: 100,
            pitch: 1
        }
    },
    {
        identifier: "rustic:chandelier_copper_oxidized",
        entity: "rustic:chandelier_entity_copper_oxidized",
        item: "rustic:chandelier_copper_oxidized",
        sound: {
            name: "random.anvil_land",
            volume: 100,
            pitch: 1
        }
    }
]

export const blockList = [
    "minecraft:air",
    "minecraft:water",
    "minecraft:flowing_water",
    "minecraft:lava",
    "minecraft:flowing_lava",
    "minecraft:fire",
    "minecraft:vine",
    "minecraft:glow_lichen",
    "minecraft:deadbush",
    "minecraft:short_grass",
    "minecraft:tall_grass",
    "minecraft:large_fern",
    "minecraft:fern",
    "minecraft:kelp",
    "minecraft:seagrass",
    "minecraft:warped_roots",
    "minecraft:crimson_roots",
    "minecraft:nether_sprouts"
    ];