import { world, system } from "@minecraft/server";

/**
 * Weighted list of zombie types to spawn in corruption zones
 */
const zombieSpawnList = [
    { id: "lv_zo:zomb", weight: 60, office: [6, 7, 8], medieval: [5], pool: [9], farm: [4] },
    { id: "lv_zo:small_zomb", weight: 40, office: [7, 8], medieval: [4], pool: [5], farm: [2,3] },
    { id: "lv_zo:chubby", weight: 40, office: [6, 7, 8], medieval: [5], pool: [3], farm: [4] },
    { id: "lv_zo:zombomb", weight: 10, office: [5], medieval: [2], pool: [3], farm: [1] },
    { id: "lv_zo:slime_shooter", weight: 10, office: [5], medieval: [2], pool: [3], farm: [1] },
    { id: "lv_zo:slapstick", weight: 10, office: [0], medieval: [3], pool: [2], farm: [4] },
    { id: "lv_zo:tanky", weight: 2, office: [3], medieval: [5], pool: [1], farm: [0] }
];

/**
 * Spawns a camp of zombies around the given source block using spreadplayers command
 * @param {Block} sourceBlock - The block that triggered the spawn
 * @param {Object} options - Configuration options
 * @returns {number} - Number of zombies successfully spawned
 */
export function spawnZombieFeature(sourceBlock, options = {}) {
    const count = options.count ?? randomInt(3, 8);
    const radius = options.radius ?? 5;
    const office = options.office ?? false;
    const pool = options.pool ?? false;
    const farm = options.farm ?? false;
    const medieval = options.medieval ?? false;
    const zombieTypes = options.zombieTypes ?? zombieSpawnList;
    const spreadDistance = options.spreadDistance ?? 6;

    const dimension = sourceBlock.dimension;
    const centerPos = sourceBlock.location;

    const spawnPos = {
        x: centerPos.x,
        y: centerPos.y + 3,
        z: centerPos.z
    };

    let successfulSpawns = 0;
    const spawnedEntities = [];

    for (let i = 0; i < count; i++) {
        const zombieType = selectWeightedRandomFromObjects(zombieTypes);
        const zombie = dimension.spawnEntity(zombieType.id, spawnPos);

        if (zombie) {
            successfulSpawns++;
            spawnedEntities.push(zombie);

            let skinValue = 0;

            if (office && zombieType.office?.length > 0) {
                skinValue = randomElement(zombieType.office);
            } else if (medieval && zombieType.medieval?.length > 0) {
                skinValue = randomElement(zombieType.medieval);
            } else if (pool && zombieType.pool?.length > 0) {
                skinValue = randomElement(zombieType.pool);
            } else if (farm && zombieType.farm?.length > 0) {
                skinValue = randomElement(zombieType.farm);
            }


            if (skinValue !== 0) {
                zombie.setProperty("lv_zo:skin", skinValue);
            }
        }
    }

    if (spawnedEntities.length > 0) {
        system.runTimeout(() => {
            executeSpreadPlayersCommand(sourceBlock, centerPos, spreadDistance, radius);
        }, 2);
    }

    return successfulSpawns;
}


function randomElement(array) {
    return array[Math.floor(Math.random() * array.length)];
}

/**
 * Selects a random object from an array of objects with weight properties
 * @param {Array} objectsWithWeights - Array of objects with weight properties
 * @returns {Object} - The selected object
 */
function selectWeightedRandomFromObjects(objectsWithWeights) {
    // Calculate total weight
    const totalWeight = objectsWithWeights.reduce((sum, item) => sum + item.weight, 0);

    // Generate random value between 0 and total weight
    let randomValue = Math.random() * totalWeight;

    // Find the object based on weight
    for (const item of objectsWithWeights) {
        randomValue -= item.weight;
        if (randomValue <= 0) {
            return item;
        }
    }

    // Fallback to first item
    return objectsWithWeights[0];
}

/**
 * Executes the spreadplayers command to distribute zombie entities
 * @param {Vector3} center - Center position for spreading
 * @param {number} spreadDistance - Minimum distance between entities
 * @param {number} maxRange - Maximum range from center
 */
export function executeSpreadPlayersCommand(source, center, spreadDistance, maxRange) {
    try {
        // Format the command with target selector for zombie family entities
        const command = `spreadplayers ${center.x} ${center.z} ${spreadDistance} ${maxRange} @e[family=zombie,r=25, x=${source.location.x}, y=${source.location.y}, z=${source.location.z}]`;


        // Run the command - this requires appropriate permissions
        world.getDimension("overworld").runCommand(command);
        return true;
    } catch (error) {
        console.warn(`Failed to execute spreadplayers command: ${error}`);
        return false;
    }
}

/**
 * Returns a random integer between min and max (inclusive)
 * @param {number} min - Minimum value
 * @param {number} max - Maximum value
 * @returns {number} - Random integer
 */
export function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}