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


class Transplanter {
    constructor() {
        this.validSeeds = [
            "minecraft:wheat_seeds", "minecraft:carrot", "minecraft:potato",
            "minecraft:beetroot_seeds", "minecraft:pumpkin_seeds", "minecraft:melon_seeds",
            "minecraft:torchflower_seeds", "minecraft:pitcher_pod"
        ];
        this.seedsBlock = [
            "minecraft:wheat", "minecraft:carrots", "minecraft:potatoes",
            "minecraft:beetroot", "minecraft:pumpkin_stem", "minecraft:melon_stem",
            "minecraft:torchflower_crop", "minecraft:pitcher_crop"
        ];
        this.tickCpt = 0;
    }

    onItemUse(e) {
        const { itemStack, source } = e;
        if (source.typeId === "minecraft:player" && itemStack.typeId === "pb_red:spawn_transplanter") {
            const minecart = source.getEntitiesFromViewDirection()[0]?.entity;
            if (!minecart) return;
            const alreadyTransplanter = source.dimension.getEntities({ type: "pb_red:transplanter", location: minecart.location, maxDistance: 1 })[0]
            if (alreadyTransplanter) return;
            if (minecart.typeId === "minecraft:minecart" && this.isWithinDistance(minecart.location, source.location, 6)) {
                minecart.runCommand(`ride @s summon_rider pb_red:transplanter`);
                const transplanterEntity = source.dimension.getEntities({ type: "pb_red:transplanter", location: minecart.location, maxDistance: 1 })[0]
                transplanterEntity.nameTag = "§r"
                minecart.dimension.runCommand(`playsound mob.agent.spawn @a ${minecart.location.x} ${minecart.location.y} ${minecart.location.z}`);
                source.runCommand(`clear @s ${itemStack.typeId} 0 1`);
            }
        }
    }

    isWithinDistance(pos1, pos2, maxDistance) {
        const distance = Math.sqrt(
            Math.pow(pos2.x - pos1.x, 2) +
            Math.pow(pos2.y - pos1.y, 2) +
            Math.pow(pos2.z - pos1.z, 2)
        );
        return distance <= maxDistance;
    }

    onScriptEventReceive(data) {
        const { id, sourceEntity } = data;

        if (id === 'pb_red:transplanter_despawn') {
            this.handleTransplanterDespawn(sourceEntity);
        } else if (id === 'pb_red:transplanter_plant') {
            this.handleTransplanterPlant(sourceEntity);
        }
    }

    handleTransplanterDespawn(sourceEntity) {
        const inv = sourceEntity.getComponent('inventory').container;
        const location = { x: sourceEntity.location.x, y: sourceEntity.location.y + 1, z: sourceEntity.location.z };
        for (let i = 0; i < inv.size; i++) {
            const item = inv.getItem(i);
            if (item) sourceEntity.dimension.spawnItem(item, location);
        }
        sourceEntity.dimension.spawnItem(new ItemStack("pb_red:spawn_transplanter", 1), location);
        sourceEntity.dimension.runCommand(`playsound random.break @a ${sourceEntity.location.x} ${sourceEntity.location.y} ${sourceEntity.location.z}`);
        sourceEntity.remove();
    }

    handleTransplanterPlant(sourceEntity) {
        if (!sourceEntity) return;

        try {
            let removeDimension = sourceEntity.dimension;
        } catch {
            // console.warn('Transplanter has been removed');
            return;
        }

        const minecart = sourceEntity.dimension.getEntities({
            location: sourceEntity.location,
            maxDistance: 1,
            type: 'minecraft:minecart'
        })[0];

        if (!minecart) return;

        sourceEntity.setRotation({
            x: minecart.getRotation().x,
            y: minecart.getRotation().y + 90
        });

        const inv = sourceEntity.getComponent('inventory').container;
        let globalSpeed = Math.sqrt(sourceEntity.getVelocity().x ** 2 + sourceEntity.getVelocity().z ** 2);

        let emptySlot = 0;
        for (let i = 0; i < inv.size; i++) {
            const item = inv.getItem(i);
            if (item && this.validSeeds.includes(item.typeId)) {
                sourceEntity.setProperty("pb_red:transplanter_crop_display", this.validSeeds.indexOf(item.typeId));
                break;
            } else {
                emptySlot++;
            }
        }

        if (emptySlot === inv.size) {
            sourceEntity.setProperty("pb_red:transplanter_crop_display", 8);
        }

        if (globalSpeed < 0.01) return;

        const viewDirection = sourceEntity.getRotation().y;
        if (viewDirection % 90 !== 0) return;

        const offsets = this.getOffsetsByViewDirection(viewDirection);
        this.tickCpt++
        if (this.tickCpt % 50 == 0) {
            sourceEntity.dimension.runCommand(`playsound pb_red.transplanter_loop @a ${sourceEntity.location.x} ${sourceEntity.location.y} ${sourceEntity.location.z} 0.8`);
        }

        offsets.forEach(offset => {
            const blockPos = {
                x: sourceEntity.location.x + offset.x,
                y: sourceEntity.location.y,
                z: sourceEntity.location.z + offset.z
            };
            this.plantSeedIfPossible(sourceEntity, inv, blockPos);
        });
    }

    getOffsetsByViewDirection(viewDirection) {
        switch (viewDirection) {
            case 0:
            case 360:
                return [
                    { x: 1, z: 0 }, { x: 2, z: 0 }, { x: 3, z: 0 },
                    { x: -1, z: 0 }, { x: -2, z: 0 }, { x: -3, z: 0 }
                ];
            case 90:
            case -270:
                return [
                    { x: 0, z: 1 }, { x: 0, z: 2 }, { x: 0, z: 3 },
                    { x: 0, z: -1 }, { x: 0, z: -2 }, { x: 0, z: -3 }
                ];
            case 180:
            case -180:
                return [
                    { x: -1, z: 0 }, { x: -2, z: 0 }, { x: -3, z: 0 },
                    { x: 1, z: 0 }, { x: 2, z: 0 }, { x: 3, z: 0 }
                ];
            case 270:
            case -90:
                return [
                    { x: 0, z: -1 }, { x: 0, z: -2 }, { x: 0, z: -3 },
                    { x: 0, z: 1 }, { x: 0, z: 2 }, { x: 0, z: 3 }
                ];
            default:
                return [];
        }
    }

    plantSeedIfPossible(sourceEntity, inv, blockPos) {
        if (!sourceEntity) return
        const testForBlock = sourceEntity.dimension.getBlock(blockPos)
        if (!testForBlock) return
        const block = testForBlock.below();
        const blockBelow = block.below();
        if (!block || !blockBelow) return
        if (block.permutation.matches("minecraft:air") && blockBelow.permutation.matches("minecraft:farmland")) {
            for (let i = 0; i < inv.size; i++) {
                const item = inv.getItem(i);

                if (item && this.validSeeds.includes(item.typeId) && item.amount > 0) {
                    let blockId = this.seedsBlock[this.validSeeds.indexOf(item.typeId)];
                    block.setPermutation(BlockPermutation.resolve(blockId));
                    if (item.amount === 1) {
                        inv.setItem(i, null);
                    } else {
                        item.amount--;
                        inv.setItem(i, item);
                    }
                    break;
                }
            }
        }
    }
}



const transplanter = new Transplanter();
world.afterEvents.itemUse.subscribe((e) => {
    transplanter.onItemUse(e)
})

system.afterEvents.scriptEventReceive.subscribe((data) => {
    transplanter.onScriptEventReceive(data)
})
