import { world } from "@minecraft/server";
import CustomVector3 from "../../calc/vector3";
export class MultiDestroyBlockItem {
    constructor(config) {
        this.config = config;
    }
    static registerBehavior(config) {
        const eventItem = new MultiDestroyBlockItem(config);
        this.items.push(eventItem);
    }
    static initialize() {
        world.afterEvents.playerBreakBlock.subscribe((event) => {
            const tool = event.itemStackBeforeBreak;
            if (!tool)
                return;
            const enchantments = tool.getComponent("minecraft:enchantable");
            const configItem = MultiDestroyBlockItem.items.find((f) => f.config.id === tool.typeId);
            if (!configItem)
                return;
            if (!this.isBlockMatchingFilter(event.brokenBlockPermutation, configItem.config.include, configItem.config.exclude))
                return;
            const block = event.block;
            const options = configItem.config.accuracy;
            let accuracyLevel = options.minAccuracyPct; // Default to minAccuracyPct
            if (enchantments) {
                const enchantmentLevel = enchantments.getEnchantment(options.enchantment)?.level ?? 0;
                const maxLevel = options.maxLevel || 1;
                accuracyLevel =
                    options.minAccuracyPct +
                        (options.maxAccuracyPct - options.minAccuracyPct) * (enchantmentLevel / maxLevel);
            }
            const neighbors = [];
            for (let x = -configItem.config.range; x <= configItem.config.range; x++) {
                for (let y = -configItem.config.range; y <= configItem.config.range; y++) {
                    for (let z = -configItem.config.range; z <= configItem.config.range; z++) {
                        if (x === 0 && y === 0 && z === 0)
                            continue; // Skip the original block
                        const offsetLocation = CustomVector3.fromMC(block.location).add(new CustomVector3(x, y, z));
                        const neighborBlock = block.dimension.getBlock(offsetLocation.toMC());
                        if (neighborBlock && Math.random() < accuracyLevel / 100) {
                            neighbors.push(neighborBlock);
                        }
                    }
                }
            }
            neighbors.forEach((neighbor) => {
                if (neighbor.typeId === "minecraft:air")
                    return;
                if (neighbor &&
                    this.isBlockMatchingFilter(neighbor.permutation, configItem.config.include, configItem.config.exclude)) {
                    if (configItem.config.dropsLoot === false) {
                        neighbor.setType("air");
                    }
                    else {
                        const loc = neighbor.location;
                        neighbor.dimension.runCommand(`setblock ${loc.x} ${loc.y} ${loc.z} air destroy`);
                    }
                }
                if (configItem.config.particles) {
                    configItem.config.particles.forEach((particle) => {
                        neighbor.dimension.spawnParticle(particle, neighbor.center());
                    });
                }
            });
            if (configItem.config.sounds) {
                configItem.config.sounds.forEach((sound) => {
                    block.dimension.playSound(sound, block.center());
                });
            }
        });
    }
    static isBlockMatchingFilter(permutation, include = {}, exclude = {}) {
        const blockId = permutation.type.id;
        // Default to include all blocks if `include` is not specified
        let isIncluded = true;
        if (include.blockIds || include.blockTags || include.blockStates) {
            isIncluded = false; // Reset to false if `include` has specific filters
            if (include.blockIds && include.blockIds.includes(blockId)) {
                isIncluded = true;
            }
            if (include.blockTags && include.blockTags.some((tag) => permutation.hasTag(tag))) {
                isIncluded = true;
            }
            if (include.blockStates) {
                const stateMatches = include.blockStates.some((state) => permutation.getState(state.state) === state.value);
                if (stateMatches) {
                    isIncluded = true;
                }
            }
        }
        // Check exclusion filters separately
        let isExcluded = false;
        if (exclude.blockIds && exclude.blockIds.includes(blockId)) {
            isExcluded = true;
        }
        if (exclude.blockTags && exclude.blockTags.some((tag) => permutation.hasTag(tag))) {
            isExcluded = true;
        }
        if (exclude.blockStates) {
            const stateMatches = exclude.blockStates.some((state) => permutation.getState(state.state) === state.value);
            if (stateMatches) {
                isExcluded = true;
            }
        }
        // Final result: include if `isIncluded` is true and `isExcluded` is false
        return isIncluded && !isExcluded;
    }
}
MultiDestroyBlockItem.items = [];
