import { system, world } from "@minecraft/server";
import { Dimensions, getRandomRange } from "../../helper/utils";
import { namespace } from "../../../config/_config";
/**
 * GrazeEntity class defines entities that can graze blocks in the world when certain conditions are met.
 * This class includes functionality for replacing blocks when an entity grazes, applying slowness effects, and playing sounds.
 *
 * @param {string} id - The unique identifier for the graze entity.
 * @param {[string, string][]} replaceBlocks - An array of tuples where the first element is the block to be replaced, and the second element is the block that replaces it.
 * @param {number} time - The amount of time in seconds that the entity will spend grazing.
 * @param {number} chance - The probability (as a percentage) that the entity will graze.
 * @param {string} sound - The sound to be played when the entity successfully grazes.
 */
export class GrazeEntity {
    constructor(config) {
        this.config = config;
    }
    /**
     * Registers a graze entity with the specified configuration.
     * @param {GrazeEntityOptions} config - The configuration for the graze entity.
     */
    static registerBehavior(config) {
        const grazeEntity = new GrazeEntity(config);
        this.entities.push(grazeEntity);
    }
    /**
     * Initializes the grazing logic for registered entities by running at regular intervals.
     */
    static initialize() {
        // Repeatedly run the handleGraze method every 60 ticks (approx 3 seconds).
        system.runInterval(() => {
            this.handleGraze();
        }, 60); // 60 ticks = 3 seconds
    }
    /**
     * Handles the logic of grazing by checking each registered graze entity and performing actions.
     */
    static handleGraze() {
        for (const dimension in Dimensions) {
            for (const config of this.entities) {
                Dimensions[dimension].getEntities({ type: config.config.id }).forEach((entity) => {
                    const chance = Math.ceil(getRandomRange(0, config.config.chance)); // Determine if grazing should occur based on chance.
                    const blockBelow = entity.dimension.getBlock(entity.location)?.below(); // Block below the entity.
                    const blockIn = entity.dimension.getBlock(entity.location); // Block the entity is inside.
                    const velocity = entity.getVelocity(); // Velocity of the entity to check if it's moving.
                    if (!blockIn || !blockBelow)
                        return; // If no blocks are found, skip.
                    // Iterate over replaceBlocks array (each tuple contains a target and replacement block).
                    for (const replaceBlock of config.config.replaceBlocks) {
                        const [targetBlock, replacementBlock] = replaceBlock;
                        // If chance is met and the entity is standing still (no movement in any direction).
                        if (chance === config.config.chance &&
                            velocity.x === 0 &&
                            velocity.y === 0 &&
                            velocity.z === 0) {
                            // Check if the entity is inside a target block that can be grazed.
                            if (blockIn.permutation.matches(targetBlock)) {
                                // Start grazing the block inside the entity.
                                this.startGrazing(entity, blockIn, replacementBlock, config);
                                break; // Exit the loop after grazing starts.
                            }
                            // Check if the block below the entity is a target block that can be grazed.
                            if (blockBelow.permutation.matches(targetBlock)) {
                                // Start grazing the block below the entity.
                                this.startGrazing(entity, blockBelow, replacementBlock, config);
                                break; // Exit the loop after grazing starts.
                            }
                        }
                    }
                });
            }
        }
    }
    /**
     * Starts the grazing animation and logic for an entity and block.
     * @param {Entity} entity - The entity performing the grazing action.
     * @param {Block} block - The block to be grazed.
     * @param {string} replacementBlock - The block that will replace the grazed block.
     * @param {GrazeEntity} grazeEntity - The graze entity containing information about the grazing process.
     */
    static startGrazing(entity, block, replacementBlock, grazeEntity) {
        // Start grazing animation.
        entity.setProperty(`${namespace}:graze`, true);
        // Apply slowness effect to prevent entity from moving during grazing.
        entity.addEffect("slowness", grazeEntity.config.time * 20, {
            amplifier: 10,
            showParticles: false,
        });
        // After the grazing time, replace the block and stop grazing.
        system.runTimeout(() => {
            try {
                entity.runCommandAsync(`setblock ~ ${block.location.y} ~ ${replacementBlock}`); // Replace block.
                world.playSound(grazeEntity.config.sound, entity.location); // Play grazing sound.
                // Stop grazing animation.
                entity.setProperty(`${namespace}:graze`, false);
            }
            catch { }
        }, 20 * grazeEntity.config.time); // Convert grazing time to ticks (1 second = 20 ticks).
    }
}
GrazeEntity.entities = [];
