import { MinecraftDimensionTypes, system, world } from "@minecraft/server";
import { isAnimal, isMonster } from "nps_tbe/others/my_API";
import { TBEPDP } from "./customPlayer";
import { PlayerBiomes } from "./specialEffects";
var Biome;
(function (Biome) {
    Biome["Amanita"] = "nps_tbe:amanita";
    Biome["Chlorophos"] = "nps_tbe:chlorophos";
    Biome["Cortinarius"] = "nps_tbe:cortinarius";
    Biome["Lactarius"] = "nps_tbe:lactarius";
    Biome["Russula"] = "nps_tbe:russula";
    Biome["Umbromycelia"] = "nps_tbe:umbromycelia";
})(Biome || (Biome = {}));
class BiomeSettings {
    constructor(globalCap = 200, animalCap = 100, ambientCap = 50, mobCap = 100, monsterSpawnChance = 0.25, animalSpawnChance = 0.25, ambientSpawnChance = 0.125, allowedSpawnBlocks = ["minecraft:end_stone"]) {
        this.globalCap = globalCap;
        this.animalCap = animalCap;
        this.ambientCap = ambientCap;
        this.mobCap = mobCap;
        this.monsterSpawnChance = monsterSpawnChance;
        this.animalSpawnChance = animalSpawnChance;
        this.ambientSpawnChance = ambientSpawnChance;
        this.allowedSpawnBlocks = allowedSpawnBlocks;
    }
}
class PopulationControl {
    static runInterval() {
        const endDimension = world.getDimension(MinecraftDimensionTypes.theEnd);
        const playersInDimension = endDimension.getPlayers();
        if (playersInDimension.length === 0)
            return;
        for (const player of playersInDimension) {
            const nearbyEntities = player.dimension.getEntities({
                maxDistance: 128,
                location: player.location
            });
            const playerBiome = this.getBiome(player);
            //console.warn('playerBiome:', playerBiome);
            const biomeSettings = playerBiome && this.biomeSettings[playerBiome]
                ? this.biomeSettings[playerBiome]
                : new BiomeSettings();
            const { globalCap, animalCap, ambientCap, mobCap, monsterSpawnChance, animalSpawnChance, ambientSpawnChance } = biomeSettings;
            const totalEntityWeight = PopulationControl.calculateTotalWeight(nearbyEntities);
            if (totalEntityWeight >= globalCap)
                return;
            const monsterWeight = PopulationControl.calculateMonsterWeight(nearbyEntities);
            const animalWeight = PopulationControl.calculateAnimalWeight(nearbyEntities);
            const ambientWeight = PopulationControl.calculateAmbientWeight(nearbyEntities);
            // Calcul des ratios
            const monsterRatio = monsterWeight / mobCap;
            const animalRatio = animalWeight / animalCap;
            const ambientRatio = ambientWeight / ambientCap;
            // Ajustement des chances en fonction de la densité
            const adjustedMonsterSpawnChance = monsterSpawnChance * (1 - monsterRatio);
            const adjustedAnimalSpawnChance = animalSpawnChance * (1 - animalRatio);
            const adjustedAmbientSpawnChance = ambientSpawnChance * (1 - ambientRatio);
            //console.warn('Apparition m:', adjustedMonsterSpawnChance)
            // Apparition de monstres
            if (monsterWeight < mobCap && Math.random() < adjustedMonsterSpawnChance) {
                //console.warn('Apparition monstres')
                PopulationControl.attemptSpawn(player, endDimension, player.location, PopulationControl.monsterConfigs);
            }
            // Apparition d'animaux
            if (animalWeight < animalCap && Math.random() < adjustedAnimalSpawnChance) {
                PopulationControl.attemptSpawn(player, endDimension, player.location, PopulationControl.animalConfigs);
            }
            // Apparition d'entités d'ambiance
            if (ambientWeight < ambientCap && Math.random() < adjustedAmbientSpawnChance) {
                PopulationControl.attemptSpawn(player, endDimension, player.location, PopulationControl.ambientConfigs);
            }
        }
    }
    static attemptSpawn(player, dimension, playerLocation, entityConfigs) {
        const chosenConfig = this.chooseWeightedConfig(entityConfigs);
        if (!chosenConfig)
            return;
        const minDist = 12;
        const maxDist = 48;
        const distance = Math.random() * (maxDist - minDist) + minDist;
        const angle = Math.random() * Math.PI * 2;
        const offsetX = Math.cos(angle) * distance;
        const offsetZ = Math.sin(angle) * distance;
        const spawnLocation = {
            x: Math.floor(playerLocation.x + offsetX),
            y: Math.floor(playerLocation.y),
            z: Math.floor(playerLocation.z + offsetZ)
        };
        // Vérifier le biome si l'entité a une liste de biomes définie
        if (chosenConfig.biomes && chosenConfig.biomes.length > 0) {
            const currentBiome = this.getBiome(player);
            if (!currentBiome || !chosenConfig.biomes.includes(currentBiome)) {
                return;
            }
        }
        const count = Math.floor(Math.random() * (chosenConfig.maxGroupSize - chosenConfig.minGroupSize + 1)) + chosenConfig.minGroupSize;
        try {
            //console.warn('attemptSpawn:', chosenConfig.id, JSON.stringify(spawnLocation))
            this.spawnEntityGroup(player, dimension, spawnLocation, chosenConfig.id, count);
        }
        catch { }
    }
    static chooseWeightedConfig(entityConfigs) {
        let totalSpawnWeight = 0;
        for (const config of entityConfigs) {
            totalSpawnWeight += config.spawnWeight;
        }
        const r = Math.random() * totalSpawnWeight;
        let accum = 0;
        for (const config of entityConfigs) {
            accum += config.spawnWeight;
            if (r < accum)
                return config;
        }
        return undefined;
    }
    static spawnEntityGroup(player, dimension, center, entityId, count) {
        const spread = 3;
        for (let i = 0; i < count; i++) {
            const dx = (Math.random() - 0.5) * spread;
            const dz = (Math.random() - 0.5) * spread;
            const locationXZ = {
                x: Math.floor(center.x + dx),
                z: Math.floor(center.z + dz)
            };
            const topBlock = dimension.getTopmostBlock(locationXZ, center.y + 32);
            if (!topBlock) {
                continue;
            }
            ;
            const spawnBlock = topBlock.above();
            if (!spawnBlock) {
                continue;
            }
            ;
            const spawnLoc = spawnBlock.center();
            const biome = this.getBiome(player);
            const biomeSettings = biome && this.biomeSettings[biome]
                ? this.biomeSettings[biome]
                : new BiomeSettings();
            const topBlockId = topBlock.typeId;
            if (!biomeSettings.allowedSpawnBlocks.includes(topBlockId)) {
                continue;
            }
            try {
                //console.warn('spawnEntityGroup: entityId:', entityId, 'spawnLoc:', JSON.stringify(spawnLoc));
                dimension.spawnEntity(entityId, spawnLoc);
            }
            catch { }
        }
    }
    static calculateTotalWeight(entities) {
        let totalWeight = 0;
        for (const entity of entities) {
            const config = this.getConfigForEntity(entity.typeId);
            if (config) {
                totalWeight += config.capWeight;
            }
            else {
                const fallbackWeight = this.entityWeights[entity.typeId] ?? 1;
                totalWeight += fallbackWeight;
            }
        }
        return totalWeight;
    }
    static calculateMonsterWeight(entities) {
        let totalWeight = 0;
        for (const entity of entities) {
            if (isMonster(entity)) {
                const config = this.getConfigForEntity(entity.typeId);
                const entityWeight = config?.capWeight ?? 1;
                totalWeight += entityWeight;
            }
        }
        return totalWeight;
    }
    static calculateAnimalWeight(entities) {
        let totalWeight = 0;
        for (const entity of entities) {
            if (isAnimal(entity)) {
                const config = this.getConfigForEntity(entity.typeId);
                const entityWeight = config?.capWeight ?? 1;
                totalWeight += entityWeight;
            }
        }
        return totalWeight;
    }
    static calculateAmbientWeight(entities) {
        let totalWeight = 0;
        for (const entity of entities) {
            const config = this.getConfigForEntity(entity.typeId);
            if (config && !isAnimal(entity) && !isMonster(entity)) {
                const entityWeight = config.capWeight;
                totalWeight += entityWeight;
            }
        }
        return totalWeight;
    }
    static getConfigForEntity(entityId) {
        let found = this.monsterConfigs.find(c => c.id === entityId);
        if (found)
            return found;
        found = this.animalConfigs.find(c => c.id === entityId);
        if (found)
            return found;
        found = this.ambientConfigs.find(c => c.id === entityId);
        return found;
    }
    static getBiomeFromPlayerBiomes(playerBiome) {
        const biomeMap = {
            [PlayerBiomes.Amanita]: Biome.Amanita,
            [PlayerBiomes.Chlorophos]: Biome.Chlorophos,
            [PlayerBiomes.Cortinarius]: Biome.Cortinarius,
            [PlayerBiomes.Lactarius]: Biome.Lactarius,
            [PlayerBiomes.Russula]: Biome.Russula,
            [PlayerBiomes.Umbromycelia]: Biome.Umbromycelia,
            [PlayerBiomes.CentralIsland]: undefined
        };
        return biomeMap[playerBiome];
    }
    static getBiome(player) {
        const value = player.getDynamicProperty(TBEPDP.LastVisitedBiome);
        const biomeValue = typeof value === "number" ? value : -1;
        if (biomeValue < 0 || biomeValue > PlayerBiomes.Umbromycelia)
            return undefined;
        return this.getBiomeFromPlayerBiomes(biomeValue);
    }
}
PopulationControl.biomeSettings = {
    [Biome.Amanita]: new BiomeSettings(400, 100, 100, 300, 0.95, 0.95, 0.95, ["nps_tbe:amanita_soil"]),
    [Biome.Chlorophos]: new BiomeSettings(400, 100, 100, 300, 0.95, 0.95, 0.95, ["nps_tbe:chlorophos_soil"]),
    [Biome.Cortinarius]: new BiomeSettings(400, 100, 100, 300, 0.95, 0.95, 0.95, ["nps_tbe:cortinarius_soil"]),
    [Biome.Lactarius]: new BiomeSettings(400, 100, 100, 300, 0.95, 0.95, 0.95, ["nps_tbe:lactarius_soil"]),
    [Biome.Russula]: new BiomeSettings(400, 100, 100, 400, 0.95, 0.95, 0.95, ["nps_tbe:russula_rock", "nps_tbe:russula_dirt", "nps_tbe:end_sulfur_block"]),
    [Biome.Umbromycelia]: new BiomeSettings(400, 100, 100, 400, 0.95, 0.95, 0.95, ["nps_tbe:umbrolith"]),
};
PopulationControl.monsterConfigs = [
    { id: "minecraft:enderman", spawnWeight: 6, capWeight: 10, minGroupSize: 1, maxGroupSize: 3, biomes: [Biome.Amanita, Biome.Cortinarius, Biome.Chlorophos, Biome.Lactarius, Biome.Russula, Biome.Umbromycelia] },
    { id: "nps_tbe:ashbone", spawnWeight: 7, capWeight: 10, minGroupSize: 2, maxGroupSize: 4, biomes: [Biome.Amanita, Biome.Cortinarius, Biome.Chlorophos, Biome.Lactarius, Biome.Russula, Biome.Umbromycelia] },
    { id: "nps_tbe:enderslime", spawnWeight: 5, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Amanita, Biome.Cortinarius, Biome.Chlorophos, Biome.Lactarius, Biome.Russula, Biome.Umbromycelia] },
    { id: "nps_tbe:enderspider", spawnWeight: 4, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Amanita, Biome.Cortinarius, Biome.Chlorophos, Biome.Lactarius, Biome.Russula, Biome.Umbromycelia] },
    //{ id: "nps_tbe:mimic", spawnWeight: 10, capWeight: 5, minGroupSize: 1, maxGroupSize: 1, biomes: [Biome.Amanita, Biome.Cortinarius, Biome.Cortinarius, Biome.Lactarius, Biome.Russula, Biome.Umbromycelia] },
    { id: "nps_tbe:radiant_slime", spawnWeight: 4, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Amanita] },
    { id: "nps_tbe:enderbeast", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 1, biomes: [Biome.Cortinarius] },
    //{ id: "nps_tbe:skull_slime", spawnWeight: 4, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Chlorophos] },
    { id: "nps_tbe:jellyfish", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 4, biomes: [Biome.Lactarius] },
    { id: "nps_tbe:abyss_slime", spawnWeight: 2, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Lactarius] },
    { id: "nps_tbe:quantum_slime", spawnWeight: 2, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Lactarius] },
    { id: "nps_tbe:fire_slime", spawnWeight: 4, capWeight: 10, minGroupSize: 1, maxGroupSize: 3, biomes: [Biome.Russula] },
    { id: "nps_tbe:enderscorpio", spawnWeight: 1, capWeight: 10, minGroupSize: 3, maxGroupSize: 5, biomes: [Biome.Russula] },
    { id: "nps_tbe:skiropteron", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 1, biomes: [Biome.Russula] },
    { id: "nps_tbe:scolopendra", spawnWeight: 2, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Russula] },
    { id: "nps_tbe:thornshade", spawnWeight: 2, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Russula] },
    { id: "nps_tbe:jellyfish", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 4, biomes: [Biome.Umbromycelia] },
    { id: "nps_tbe:enderbeast", spawnWeight: 1, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Umbromycelia] },
    { id: "nps_tbe:shadow_slime", spawnWeight: 2, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Umbromycelia] },
    { id: "nps_tbe:giant_endermite", spawnWeight: 2, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Umbromycelia] },
    { id: "nps_tbe:voidwalker", spawnWeight: 2, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Umbromycelia] },
    { id: "nps_tbe:shadow_slime", spawnWeight: 4, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Umbromycelia] },
    { id: "nps_tbe:abyss_slime", spawnWeight: 2, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Umbromycelia] },
    { id: "nps_tbe:quantum_slime", spawnWeight: 2, capWeight: 10, minGroupSize: 2, maxGroupSize: 3, biomes: [Biome.Umbromycelia] },
    { id: "minecraft:bogged", spawnWeight: 2, capWeight: 10, minGroupSize: 1, maxGroupSize: 4, biomes: [Biome.Amanita, Biome.Cortinarius, Biome.Lactarius] },
    { id: "nps_tbe:amanita_sporebone", spawnWeight: 2, capWeight: 10, minGroupSize: 1, maxGroupSize: 1, biomes: [Biome.Amanita] },
    { id: "nps_tbe:cortinarius_sporebone", spawnWeight: 2, capWeight: 10, minGroupSize: 1, maxGroupSize: 1, biomes: [Biome.Cortinarius] },
    { id: "nps_tbe:lactarius_sporebone", spawnWeight: 2, capWeight: 10, minGroupSize: 1, maxGroupSize: 1, biomes: [Biome.Lactarius] },
    { id: "nps_tbe:amanita_mushmauler", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Amanita] },
    { id: "nps_tbe:cortinarius_mushmauler", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Cortinarius] },
    { id: "nps_tbe:lactarius_mushmauler", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 2, biomes: [Biome.Lactarius] },
];
PopulationControl.animalConfigs = [
    { id: "nps_tbe:endertoad", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 1, biomes: [Biome.Amanita, Biome.Chlorophos, Biome.Cortinarius, Biome.Lactarius] },
    { id: "nps_tbe:butterfly", spawnWeight: 3, capWeight: 4, minGroupSize: 2, maxGroupSize: 4, biomes: [Biome.Amanita, Biome.Chlorophos, Biome.Cortinarius, Biome.Lactarius] },
    { id: "nps_tbe:dragon_fly", spawnWeight: 3, capWeight: 4, minGroupSize: 2, maxGroupSize: 4, biomes: [Biome.Amanita, Biome.Chlorophos, Biome.Cortinarius, Biome.Lactarius] },
    { id: "nps_tbe:firefly", spawnWeight: 3, capWeight: 4, minGroupSize: 2, maxGroupSize: 4, biomes: [Biome.Amanita, Biome.Chlorophos, Biome.Cortinarius, Biome.Lactarius] },
    { id: "nps_tbe:stellarmanta", spawnWeight: 1, capWeight: 10, minGroupSize: 1, maxGroupSize: 1, biomes: [Biome.Amanita, Biome.Chlorophos, Biome.Cortinarius, Biome.Lactarius] },
    { id: "nps_tbe:ladybug", spawnWeight: 3, capWeight: 10, minGroupSize: 2, maxGroupSize: 5, biomes: [Biome.Amanita, Biome.Chlorophos, Biome.Cortinarius, Biome.Lactarius] },
    { id: "nps_tbe:amanita_spoofykin", spawnWeight: 3, capWeight: 10, minGroupSize: 4, maxGroupSize: 6, biomes: [Biome.Amanita] },
    { id: "nps_tbe:chlorophos_spoofykin", spawnWeight: 3, capWeight: 10, minGroupSize: 4, maxGroupSize: 6, biomes: [Biome.Chlorophos] },
    { id: "nps_tbe:cortinarius_spoofykin", spawnWeight: 3, capWeight: 10, minGroupSize: 4, maxGroupSize: 6, biomes: [Biome.Cortinarius] },
    { id: "nps_tbe:lactarius_spoofykin", spawnWeight: 3, capWeight: 10, minGroupSize: 4, maxGroupSize: 6, biomes: [Biome.Lactarius] },
];
PopulationControl.ambientConfigs = [];
PopulationControl.entityWeights = {
    "minecraft:player": 0,
    "minecraft:item": 0,
    "nps_tbe:damage_indicator": 0
};
PopulationControl.tickInterval = 40;
system.runInterval(() => {
    if (!world.gameRules.doMobSpawning)
        return;
    PopulationControl.runInterval();
    //console.warn('PopulationControl.runInterval')
}, PopulationControl.tickInterval);
