import { world, system, ItemStack, WeatherType } from '@minecraft/server';
import { FSBlocks, MCBlockStates, MCParticles, FluidType, MCSounds, FSWorldStoredData } from '../../constants.js';
import { getBlockState, shrinkItemStack, updateBlockState, playSoundAtBlock, canBlockSeeSky, updateBlockStates, giveItemToPlayer } from '../../utils/utils.js';
import { setEntityHeldItem, getEntityHeldItem } from '../../utils/players.js';
import { CrucibleRecipes } from '../../recipes/recipes.js';
import { MinecraftBlockTypes, MinecraftItemTypes } from '../../minecraft_vanilla_data.js';

const MAX_FLUID_STAGE = 3;
world.beforeEvents.playerInteractWithBlock.subscribe((event) => {
    const block = event.block;
    const itemStack = event.itemStack;
    const player = event.player;
    if (!itemStack) {
        return;
    }
    if (itemStack.typeId !== FSBlocks.CRUCIBLE) {
        return;
    }
    if (block.typeId !== MinecraftBlockTypes.Campfire) {
        system.run(() => {
            player.onScreenDisplay.setActionBar({
                translate: "ftb_sieves.messages.crucible.wrong_block",
            });
        });
        return;
    }
    event.cancel = true;
    const oldFacing = getBlockState(block.permutation, MCBlockStates.CARDINAL_DIRECTION);
    system.runTimeout(() => {
        const newItemStack = shrinkItemStack(itemStack);
        setEntityHeldItem(player, newItemStack);
        block.setType(FSBlocks.CRUCIBLE_FIRE);
        updateBlockState(block, MCBlockStates.CARDINAL_DIRECTION, oldFacing);
    }, 0);
});
class SmokeyCrucibleBlockComponent {
    onTick(event) {
        const block = event.block;
        block.dimension.spawnParticle(MCParticles.CAMPFIRE_SMOKE, block.center());
    }
    onRandomTick(event) {
        const block = event.block;
        block.dimension.spawnParticle(MCParticles.CAMPFIRE_SMOKE, block.center());
    }
}
class CrucibleBlockComponent {
    constructor(fluids) {
        this.handleRecipeInteraction = (event) => {
            const block = event.block;
            block.dimension;
            const player = event.player;
            const itemStack = getEntityHeldItem(player);
            const itemStackId = itemStack?.typeId;
            const fluidStage = getBlockState(block.permutation, CrucibleBlockStates.FLUID_STAGE);
            const fluidType = getBlockState(block.permutation, CrucibleBlockStates.LIQUID);
            if (!itemStack) {
                return;
            }
            if (fluidType !== FluidType.AIR) {
                for (let interactrecipe of CrucibleRecipes.INTERACT_RECIPES) {
                    if (interactrecipe.isValid(fluidType, itemStack)) {
                        const output = interactrecipe.output;
                        updateBucket(player, itemStack, output);
                        playSoundAtBlock(block, interactrecipe.sound);
                        decreesFluidStage(block, fluidStage);
                        return;
                    }
                }
            }
            for (const fluidHolder of CrucibleRecipes.FLUID_HOLDERS) {
                if (!this.allowedFluids.includes(fluidHolder.fluid)) {
                    continue;
                }
                if (fluidHolder.itemId === itemStackId) {
                    if (fluidHolder.requiredLevels + fluidStage > MAX_FLUID_STAGE) {
                        continue;
                    }
                    if (!(fluidType === FluidType.AIR || fluidType === fluidHolder.fluid)) {
                        continue;
                    }
                    if (fluidType === FluidType.AIR) {
                        updateBlockState(block, CrucibleBlockStates.LIQUID, fluidHolder.fluid);
                    }
                    increaseFluidStage(block, fluidStage, fluidHolder.requiredLevels);
                    playSoundAtBlock(block, fluidHolder.fillSound);
                    updateBucket(player, itemStack, new ItemStack(fluidHolder.convertsTo, 1));
                    return;
                }
                else if (fluidHolder.convertsTo === itemStackId) {
                    if (fluidType !== fluidHolder.fluid) {
                        continue;
                    }
                    if (fluidHolder.requiredLevels > fluidStage) {
                        continue;
                    }
                    updateBucket(player, itemStack, new ItemStack(fluidHolder.itemId, 1));
                    decreesFluidStage(block, fluidStage, fluidHolder.requiredLevels);
                    playSoundAtBlock(block, fluidHolder.emptySound);
                    return;
                }
            }
        };
        this.onTick = (event) => {
            this.handleBlockTick(event.block);
            const block = event.block;
            const dimension = block.dimension;
            const stage = getBlockState(block.permutation, CrucibleBlockStates.FLUID_STAGE);
            const fluidType = getBlockState(block.permutation, CrucibleBlockStates.LIQUID);
            if (fluidType === FluidType.LAVA) {
                return;
            }
            const dimensionId = dimension.id.replace("minecraft:", "");
            const identifier = FSWorldStoredData.weather(dimensionId);
            const weather = world.getDynamicProperty(identifier);
            if (weather === WeatherType.Rain || weather === WeatherType.Thunder) {
                if (!canBlockSeeSky(block)) {
                    return;
                }
                if (fluidType === FluidType.AIR) {
                    updateBlockState(block, CrucibleBlockStates.LIQUID, FluidType.WATER);
                }
                increaseFluidStage(block, stage);
                playSoundAtBlock(block, MCSounds.CAULDRON_DRIP_WATER);
            }
            else {
                return;
            }
        };
        this.onRandomTick = (event) => {
            if (event.block.typeId !== FSBlocks.CRUCIBLE_FIRE) {
                return;
            }
            playSoundAtBlock(event.block, MCSounds.FIRE_CRACKLE, {
                volume: 5
            });
        };
        this.onPlayerInteract = (event) => {
            this.handleRecipeInteraction(event);
            const block = event.block;
            const player = event.player;
            const itemStack = getEntityHeldItem(player);
            if (!itemStack) {
                return;
            }
            const blockType = getBlockState(block.permutation, CrucibleBlockStates.BLOCK_TYPE);
            const blockStage = getBlockState(block.permutation, CrucibleBlockStates.BLOCK_STAGE);
            const fluidType = getBlockState(block.permutation, CrucibleBlockStates.LIQUID);
            const activeRecipe = CrucibleRecipes.fromRenderId(blockType);
            const wantedRecipe = CrucibleRecipes.fromItemStack(itemStack);
            if (blockStage !== 0) {
                if (this.allowedFluids.includes(FluidType.LAVA)) {
                    if (itemStack.typeId === MinecraftItemTypes.Coal || itemStack.typeId === MinecraftItemTypes.Charcoal) {
                        this.handleBlockTick(event.block);
                        setEntityHeldItem(player, shrinkItemStack(itemStack, 1));
                    }
                    return;
                }
            }
            if (!wantedRecipe) {
                return;
            }
            if (!this.allowedFluids.includes(wantedRecipe.output)) {
                return;
            }
            if (fluidType !== FluidType.AIR && wantedRecipe.output !== fluidType) {
                player.onScreenDisplay.setActionBar({
                    "translate": "ftb_sieves.messages.crucible.cant_put_different_fluid",
                });
                return;
            }
            if (activeRecipe && wantedRecipe) {
                return;
            }
            updateBlockStates(block, {
                [CrucibleBlockStates.BLOCK_TYPE]: wantedRecipe.renderId,
                [CrucibleBlockStates.BLOCK_STAGE]: 1
            });
            playSoundAtBlock(block, MCSounds.BRUSH_GENERIC);
            const itemStack1 = shrinkItemStack(itemStack);
            setEntityHeldItem(player, itemStack1);
        };
        this.allowedFluids = [...fluids, FluidType.AIR];
    }
    handleBlockTick(block) {
        const blockType = getBlockState(block.permutation, CrucibleBlockStates.BLOCK_TYPE);
        const blockStage = getBlockState(block.permutation, CrucibleBlockStates.BLOCK_STAGE);
        const fluidType = getBlockState(block.permutation, CrucibleBlockStates.LIQUID);
        const fluidStage = getBlockState(block.permutation, CrucibleBlockStates.FLUID_STAGE);
        if (blockType === "empty" || fluidStage >= 6) {
            return;
        }
        const recipe = CrucibleRecipes.fromRenderId(blockType);
        if (!recipe) {
            return;
        }
        if (!this.allowedFluids.includes(recipe.output)) {
            return;
        }
        const nextBlockStage = blockStage + 1;
        if (nextBlockStage <= 5) {
            updateBlockState(block, CrucibleBlockStates.BLOCK_STAGE, nextBlockStage);
        }
        else {
            const output = recipe.output;
            if (output === FluidType.AIR) {
                return;
            }
            if (!(fluidType === output || fluidType === FluidType.AIR)) {
                return;
            }
            if (fluidStage === MAX_FLUID_STAGE) {
                return;
            }
            updateBlockStates(block, {
                [CrucibleBlockStates.BLOCK_STAGE]: 0,
                [CrucibleBlockStates.LIQUID]: output,
                [CrucibleBlockStates.BLOCK_TYPE]: "empty",
                [CrucibleBlockStates.FLUID_STAGE]: fluidStage + 1
            });
            playSoundAtBlock(block, MCSounds.CAULDRON_TAKE);
        }
    }
}
var CrucibleBlockStates;
(function (CrucibleBlockStates) {
    CrucibleBlockStates["BLOCK_TYPE"] = "ftb_sieves:block_type";
    CrucibleBlockStates["FLUID_STAGE"] = "ftb_sieves:fluid_stage";
    CrucibleBlockStates["BLOCK_STAGE"] = "ftb_sieves:block_stage";
    CrucibleBlockStates["LIQUID"] = "ftb_sieves:liquid";
})(CrucibleBlockStates || (CrucibleBlockStates = {}));
function decreesFluidStage(block, currentStage, amount = 1) {
    const nextStage = currentStage - amount;
    if (nextStage <= 0) {
        updateBlockStates(block, {
            [CrucibleBlockStates.LIQUID]: FluidType.AIR,
            [CrucibleBlockStates.FLUID_STAGE]: 0
        });
    }
    else {
        updateBlockState(block, CrucibleBlockStates.FLUID_STAGE, nextStage);
    }
}
function increaseFluidStage(block, currentStage, amount = 1) {
    const nextStage = currentStage + amount;
    if (nextStage > MAX_FLUID_STAGE) {
        return;
    }
    updateBlockState(block, CrucibleBlockStates.FLUID_STAGE, nextStage);
}
function updateBucket(player, heldItem, newStack) {
    const itemStack = shrinkItemStack(heldItem, 1);
    if (itemStack) {
        setEntityHeldItem(player, itemStack);
        giveItemToPlayer(player, newStack);
    }
    else {
        setEntityHeldItem(player, newStack);
    }
}

export { CrucibleBlockComponent, CrucibleBlockStates, SmokeyCrucibleBlockComponent };
