import { BlockVolume } from '@minecraft/server';
import { getBlockState, updateBlockState, spawnParticleAtBlock, playSoundAtBlock, addVec3 } from '../../utils/utils.js';
import { MCSounds, MCParticles } from '../../constants.js';
import { MinecraftBlockTypes } from '../../minecraft_vanilla_data.js';
import { BlockUtils as W } from '../../ftb_bedrock_bedrock_utils_dist_bedrock_utils.js';

class BaseGrowthProcessor {
    constructor(state, maxState, allowedBlocks = []) {
        this.progressStage = (block) => {
            const state = getBlockState(block.permutation, this.state);
            if (state === undefined || state >= this.maxState) {
                return false;
            }
            updateBlockState(block, this.state, state + 1);
            return true;
        };
        this.onStageProgressed = (block) => {
            spawnParticleAtBlock(block, MCParticles.CROP_GROWTH);
            playSoundAtBlock(block, MCSounds.COMPOST_FILL);
        };
        this.canProcess = (block) => {
            return this.allowedBlocks.length === 0 || this.allowedBlocks.includes(block.typeId);
        };
        this.canBeHarvested = (block) => {
            if (!this.canProcess(block)) {
                return false;
            }
            const state = getBlockState(block.permutation, this.state);
            return state !== undefined && state >= this.maxState;
        };
        this.harvest = (block, entity) => {
            W.spawnBreakLoot(block, entity);
            updateBlockState(block, this.state, 0);
            this.onStageProgressed(block);
            return true;
        };
        this.state = state;
        this.maxState = maxState;
        this.allowedBlocks = allowedBlocks;
    }
}
class SaplingGrowthProcessor {
    constructor(blockId, structureName) {
        this.progressStage = (block) => {
            block.setType(MinecraftBlockTypes.Air);
            spawnParticleAtBlock(block, MCParticles.CROP_GROWTH);
            return block.dimension.placeFeature(this.structureName, block.location);
        };
        this.onStageProgressed = (block) => {
        };
        this.canProcess = (block) => {
            return block.typeId === this.blockId;
        };
        this.onStageProgressedFailed = (block) => {
            block.setType(this.blockId);
        };
        this.canBeHarvested = (block) => false;
        this.harvest = (block, entity) => {
            return false;
        };
        this.blockId = blockId;
        this.structureName = structureName;
    }
}
class TwoByTwoSaplingGrowthProcessor extends SaplingGrowthProcessor {
    constructor(blockId, structureName) {
        super(blockId, structureName);
        this.progressStage = (block) => {
            for (let xOffset = -1; xOffset <= 1; xOffset++) {
                for (let zOffset = -1; zOffset <= 1; zOffset++) {
                    if (xOffset === 0 && zOffset === 0) {
                        continue;
                    }
                    let count = 0;
                    const blocks2x2 = getBlocks2x2(block, xOffset, zOffset);
                    const blockToUpdate = [];
                    for (const foundBlock of blocks2x2) {
                        count++;
                        blockToUpdate.push(block.dimension.getBlock(foundBlock));
                    }
                    if (count === 4) {
                        for (const foundBlock of blockToUpdate) {
                            block.dimension.getBlock(foundBlock).setType(MinecraftBlockTypes.Air);
                        }
                        spawnParticleAtBlock(block, MCParticles.CROP_GROWTH);
                        block.dimension.placeFeature(this.structureName, block.location);
                        return true;
                    }
                }
            }
            return false;
        };
        this.canProcess = (block) => {
            if (block.typeId !== this.blockId) {
                return false;
            }
            for (let xOffset = -1; xOffset <= 1; xOffset++) {
                for (let zOffset = -1; zOffset <= 1; zOffset++) {
                    if (xOffset === 0 || zOffset === 0) {
                        continue;
                    }
                    let count = 0;
                    for (const _ of getBlocks2x2(block, xOffset, zOffset)) {
                        count++;
                    }
                    if (count === 4) {
                        return true;
                    }
                }
            }
            return false;
        };
        this.canBeHarvested = (block) => false;
        this.harvest = (block, entity) => {
            return false;
        };
    }
}
function getBlocks2x2(blockCenter, xOffset, zOffset) {
    const blockLocation = blockCenter.location;
    const blockVolume = new BlockVolume(blockLocation, addVec3(blockLocation, xOffset, 0, zOffset));
    const blocks = blockCenter.dimension.getBlocks(blockVolume, {
        includeTypes: [blockCenter.typeId]
    });
    return blocks.getBlockLocationIterator();
}

export { BaseGrowthProcessor, SaplingGrowthProcessor, TwoByTwoSaplingGrowthProcessor };
