import { world, system, ItemStack } from "@minecraft/server";
import '../../spawn_loot/spawn_loot';
import { oliveSeeds, appleSeeds, sugar } from "./seedsLootTable";

const itemsConfig = {
    wildberries: {
        soundId: "use.slime",
        recipes: {
            "minecraft:glass_bottle": "rustic:bottle_of_wildberry_juice",
            "minecraft:bucket": "rustic:wildberry_juice_bucket"
        }
    },
    ironberries: {
        soundId: "use.slime",
        recipes: {
            "minecraft:glass_bottle": "rustic:bottle_of_ironberry_juice",
            "minecraft:bucket": "rustic:ironberry_juice_bucket"
        }
    },
    grapes: {
        soundId: "use.slime",
        recipes: {
            "minecraft:glass_bottle": "rustic:bottle_of_grape_juice",
            "minecraft:bucket": "rustic:grape_juice_bucket"
        }
    },
    olives: {
        soundId: "use.slime",
        recipes: {
            "minecraft:glass_bottle": "rustic:bottle_of_olive_oil",
            "minecraft:bucket": "rustic:olive_oil_bucket"
        }
    },
    apple: {
        soundId: "use.slime",
        recipes: {
            "minecraft:glass_bottle": "rustic:bottle_of_apple_juice",
            "minecraft:bucket": "rustic:apple_juice_bucket"
        }
    },
    honeycomb: {
        soundId: "use.slime",
        recipes: {
            "minecraft:glass_bottle": "minecraft:honey_bottle",
            "minecraft:bucket": "rustic:honey_bucket"
        }
    },
    sugar_cane: {
        soundId: "dig.grass",
        recipes: {
            "minecraft:glass_bottle": "minecraft:potion",
            "minecraft:bucket": "minecraft:water_bucket"
        }
    }
};
const pileAmount = {
    1: "minecraft:dirt",
    2: "minecraft:string",
    3: "minecraft:feather",
    4: "minecraft:egg",
    5: "minecraft:flint",
    6: "minecraft:stick"
};

system.beforeEvents.startup.subscribe((initEvent) => {
    initEvent.blockComponentRegistry.registerCustomComponent("rustic:crushing_tub", {
        onEntityFallOn: e => {
            const { entity, block, fallDistance, dimension } = e;
            let itemState, itemPile;
            const entities = dimension.getEntitiesAtBlockLocation(block.center());
            for (const entity of entities)if(entity.typeId == "rustic:crushing_tub_item_pile")itemState = entity.getDynamicProperty("rustic:item_pile"),itemPile = entity;
            const liquidState = block.permutation.getState("r:liquid");
            const typeState = block.permutation.getState("r:type");
            const particle = "rustic:" + typeState + "_particle"

            if (itemState == 0 || fallDistance < 1 || liquidState == 6 || !itemPile) return;

            if (itemState == 1)itemPile?.remove();
            else {
                itemPile?.setDynamicProperty("rustic:item_pile",itemState - 1);
                itemPile?.runCommand(`replaceitem entity @s slot.weapon.mainhand 1 ${pileAmount[itemState - 1]}`)
            }
            

            if (liquidState < 6) block.setPermutation(block.permutation.withState("r:liquid", liquidState + 1));
            dimension.playSound(itemsConfig[typeState].soundId,block.center(),{volume: 0.8})

            if (typeState == "apple") block.dimension.spawnLoot(appleSeeds, block.center())
            if (typeState == "olives") block.dimension.spawnLoot(oliveSeeds, block.center())
            if (typeState == "sugar_cane") block.dimension.spawnLoot(sugar, block.center())

            dimension.runCommand(`particle ${particle} ${block.center().x} ${block.center().y} ${block.center().z}`)
            
        },
    });
});


//Crops Interaction
world.beforeEvents.playerInteractWithBlock.subscribe(eventData => {
    const block = eventData.block;
    const dimension = block.dimension;
    const item = eventData.itemStack;
    const player = eventData.player;

    if (!block.hasTag("CrushingTub") || !item)return;

    const blockType = block.permutation.getState("r:type");
    const liquidLevel = block.permutation.getState("r:liquid");
    const state = item.typeId.split(":")[1];
    let itemPile;
    const entities = dimension.getEntitiesAtBlockLocation(block.center());
    for (const entity of entities)if(entity.typeId == "rustic:crushing_tub_item_pile")itemPile = entity;
    
    if(!itemsConfig[state])return;

    let stateNumber = 1
    if(blockType == 'none' || !itemPile && blockType == state){
        if(player.isSneaking)stateNumber = item.amount > 6 ? 6 : item.amount;
        system.run( () => {
            block.setPermutation(block.permutation.withState("r:type", state));
            const itemPile = dimension.spawnEntity("rustic:crushing_tub_item_pile", {x: block.center().x, y: block.center().y-0.4, z:block.center().z},{spawnEvent: `rustic:change_to_${state}`});
            itemPile.setDynamicProperty("rustic:item_pile",stateNumber);
            if (stateNumber != 1)itemPile.runCommand(`replaceitem entity @s slot.weapon.mainhand 1 ${pileAmount[stateNumber]}`)
            block.dimension.playSound(itemsConfig[state].soundId,block.center(),{volume: 0.8})
            removeItem(player,item,stateNumber)
        })
    }
    else if (blockType == state){
        system.run( () => {
            const entities = dimension.getEntitiesAtBlockLocation(block.center());
            let itemState = 0;
            for (const itemPile of entities){
                if (itemPile.typeId != "rustic:crushing_tub_item_pile")return;
                itemState = itemPile.getDynamicProperty("rustic:item_pile");
                if (itemState == 6) return;
                stateNumber = itemState + 1
                itemPile.setDynamicProperty("rustic:item_pile",stateNumber);
                itemPile.runCommand(`replaceitem entity @s slot.weapon.mainhand 1 ${pileAmount[stateNumber]}`)
            }
            dimension.playSound(itemsConfig[state].soundId,block.center(),{volume: 0.8});
            if(player.isSneaking && itemState != 0)stateNumber = 1;
            removeItem(player,item,1)
        })
    }
    eventData.cancel = true
});

//Hand Interaction
world.beforeEvents.playerInteractWithBlock.subscribe(eventData => {
    const block = eventData.block;
    const dimension = block.dimension;
    const item = eventData.itemStack;
    const player = eventData.player;

    if (!block.hasTag("CrushingTub") || item || !player.isSneaking)return;

    const blockState = block.permutation.getState("r:type");
    let itemState, itemPile;
    const entities = dimension.getEntitiesAtBlockLocation(block.center());
    for (const entity of entities)if(entity.typeId == "rustic:crushing_tub_item_pile")itemState = entity.getDynamicProperty("rustic:item_pile"),itemPile = entity;
    const liquidState = block.permutation.getState("r:liquid");

    if (itemState < 1 || blockState == 'none' || !itemPile) return;

    let itemId = ["apple", "honeycomb", "sugar_cane"].includes(blockState) ? "minecraft:" : "rustic:";
    itemId += blockState

    system.run( () => {
        dimension.playSound(itemsConfig[blockState].soundId,block.center(),{volume: 0.8});
        addItem(player,itemId,1)
        if (itemState == 1){
            if (liquidState == 0)block.setPermutation(block.permutation.withState("r:type", 'none'));
            itemPile.remove()
            return;
        }
        itemPile.setDynamicProperty("rustic:item_pile",itemState - 1);
        itemPile.runCommand(`replaceitem entity @s slot.weapon.mainhand 1 ${pileAmount[itemState - 1]}`)
    })

    eventData.cancel = true
});

//Glass Bottle Interaction

world.beforeEvents.playerInteractWithBlock.subscribe(eventData => {
    const block = eventData.block;
    const dimension = block.dimension;
    const item = eventData.itemStack;
    const player = eventData.player;

    if (!block.hasTag("CrushingTub"))return;

    if (item == undefined) return;

    if (item.typeId != "minecraft:glass_bottle" && item.typeId != "minecraft:bucket") return;


    const blockState = block.permutation.getState("r:type");
    const liquidState = block.permutation.getState("r:liquid");
    let itemState = 0;
    const entities = dimension.getEntitiesAtBlockLocation(block.center());
    for (const entity of entities)if(entity.typeId == "rustic:crushing_tub_item_pile")itemState = entity.getDynamicProperty("rustic:item_pile");

    if (item.typeId == "minecraft:glass_bottle" && liquidState < 2) return;

    if (item.typeId == "minecraft:bucket" && liquidState < 6) return;

    if(blockState == 'none') return;

    if(liquidState < 1) return;

    let itemToFill = undefined
    if (itemsConfig[blockState]?.recipes?.[item.typeId]) {
        itemToFill = itemsConfig[blockState].recipes[item.typeId];
    }
    const height = item.typeId == "minecraft:glass_bottle" ? 2 : 6
    const sound = item.typeId == "minecraft:glass_bottle" ? "bottle.fill" : "cauldron.takepotion"

    system.run( () => {
        if (itemState == 0 && (liquidState == 2 || height == 6)){
            block.setPermutation(block.permutation.withState("r:type", 'none'));
        }
        block.setPermutation(block.permutation.withState("r:liquid", liquidState - height));
        block.dimension.runCommand(`playsound ${sound} @a ${block.x} ${block.y} ${block.z} 10 0.8`)

        const equipment = player.getComponent('equippable');
        if (item.amount == 1){
            equipment.setEquipment('Mainhand', new ItemStack(itemToFill, 1));
        }
        else{
            if (player.getGameMode() != "Creative")item.amount -= 1;
            equipment.setEquipment('Mainhand', item);
            player.getComponent("inventory").container.addItem(new ItemStack(itemToFill, 1))
        }
    })

    eventData.cancel = true
});




export function removeItem(player,item, count){
    const equipment = player.getComponent('equippable');
    system.run( () => {
        if (player.getGameMode() !== "Creative") {
            if (item.amount > count) {
                item.amount -= count;
                equipment.setEquipment('Mainhand', item);
            } else if (item.amount === count) {
                equipment.setEquipment('Mainhand', undefined);
            }
        }
    })
}

export function addItem(player,item,count){
    player.getComponent('inventory').container.addItem(new ItemStack(item, count));
}

