import { EntityComponentTypes, GameMode, Player, world } from "@minecraft/server";
// 2025-9-26
// 本文件为函数文件和类型文件
// 因为图方便大部分函数为AI代替实现
// 从数组中随机获取指定数量的元素
export function getRandomElements(arr, count) {
    if (Array.isArray(arr)) {
        if (count >= arr.length) {
            return [...arr];
        }
    }
    else {
        return [arr];
    }
    const result = [];
    const tempArr = [...arr];
    for (let i = 0; i < count; i++) {
        const randomIndex = Math.floor(Math.random() * tempArr.length);
        result.push(tempArr[randomIndex]);
        tempArr.splice(randomIndex, 1); // 移除已选元素，避免重复
    }
    return result;
}
// 洗牌函数，随机打乱数组元素顺序
export function shuffle(array) {
    // 创建数组的副本，不修改原数组
    const shuffled = Array.isArray(array) ? [...array] : [array];
    const length = shuffled.length;
    // Fisher-Yates 洗牌算法
    for (let i = length - 1; i > 0; i--) {
        // 随机生成 0 到 i 之间的索引
        const randomIndex = Math.floor(Math.random() * (i + 1));
        // 交换当前元素和随机位置的元素
        [shuffled[i], shuffled[randomIndex]] = [shuffled[randomIndex], shuffled[i]];
    }
    return shuffled;
}
// 随机数
export function randint(min, max, floating = false) {
    // 参数验证
    if (min > max) {
        throw new Error('最小值不能大于最大值');
    }
    if (!Number.isFinite(min) || !Number.isFinite(max)) {
        throw new Error('参数必须是有效数字');
    }
    if (floating) {
        // 浮点数版本：生成[min, max]范围内的随机浮点数
        return Math.random() * (max - min) + min;
    }
    else {
        // 整数版本：生成[min, max]范围内的随机整数
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
}
export function getRandomXZOffset(intensity) {
    if (intensity <= 0) {
        return {
            x: 0,
            z: 0,
        };
    }
    // 生成-1到1之间的随机数，然后乘以强度
    const randomX = (Math.random() * 2 - 1) * intensity;
    const randomZ = (Math.random() * 2 - 1) * intensity;
    return {
        x: randomX,
        z: randomZ
    };
}
// 获取实体生成的最高Y值
export function getSpawnY(location, dimensionId) {
    // 从位置向上遍历是空气或者水或者岩浆类型
    for (let i = location.y; i < world.getDimension(dimensionId).heightRange.max; i++) {
        let block = world.getDimension(dimensionId).getBlock({
            x: location.x,
            y: i,
            z: location.z
        });
        if ((block === null || block === void 0 ? void 0 : block.typeId) == 'minecraft:air' || (block === null || block === void 0 ? void 0 : block.typeId) == 'minecraft:water' || (block === null || block === void 0 ? void 0 : block.typeId) == 'minecraft:lava') {
            return i;
        }
    }
    return location.y;
}
// 随机选择事件类别（返回包含 eventName 的类别），如果长度为0则返回未定义
export function getRandomEventCategory(categories) {
    if (categories.length === 0) {
        return undefined;
    }
    // 计算总权重
    const totalWeight = categories.reduce((sum, category) => sum + category.weight, 0);
    // 生成一个随机数
    const random = Math.random() * totalWeight;
    // 根据权重选择事件类别
    let currentWeight = 0;
    for (const category of categories) {
        currentWeight += category.weight;
        if (random <= currentWeight) {
            return category;
        }
    }
    // 理论上不会执行到这里，但为了类型安全返回最后一个
    return categories[categories.length - 1];
}
// 权重函数
export function getRandomByWeight(events) {
    if (events.length === 0) {
        throw new Error('Events array cannot be empty');
    }
    // 计算总权重
    const totalWeight = events.reduce((sum, event) => sum + event.weight, 0);
    // 生成一个随机数
    const random = Math.random() * totalWeight;
    // 根据权重选择事件
    let currentWeight = 0;
    for (const event of events) {
        currentWeight += event.weight;
        if (random <= currentWeight) {
            return event;
        }
    }
    // 理论上不会执行到这里，但为了类型安全返回最后一个
    return events[events.length - 1];
}
// 生成物品辅助函数
export function spawnItem(dimension, typeId, location) {
    world.getDimension(dimension).spawnItem(typeId, location);
}
// 归一化物品数量
export function normalizeCount(value = 1) {
    if (typeof value == 'number') {
        return value;
    }
    return randint(value.min, value.max);
}
// 根据材料返回数组
export function getMaterialTypeId(material) {
    const colors = ["white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray", "light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black"];
    return colors.map(color => `minecraft:${color}_${material}`);
}
// 剥夺颜色
export function removeColor(itemTypeId) {
    return itemTypeId.replace(/^minecraft:(?:white|orange|magenta|light_blue|yellow|lime|pink|gray|light_gray|cyan|purple|blue|brown|green|red|black)_/, '');
}
// 只留颜色
export function getColor(itemTypeId) {
    const match = itemTypeId.match(/^minecraft:(white|orange|magenta|light_blue|yellow|lime|pink|gray|light_gray|cyan|purple|blue|brown|green|red|black)_/);
    return match ? match[1] : undefined;
}
// 战利品容器管理器
export class LootContainerManager {
    constructor(lootTableManager) {
        this.loot = lootTableManager;
    }
    /**
     * 将战利品表随机分布到容器中
     */
    distributeLootToContainer(container, lootTableId) {
        const table = this.loot.getLootTable(lootTableId);
        if (!table)
            return;
        if (container.size != 27 && container.size != 54)
            return;
        container.clearAll();
        const lootTable = this.loot.generateLootFromTable(table);
        if (!lootTable || lootTable.length === 0)
            return;
        const containerSize = container.size;
        // 1. 智能分裂物品堆叠
        const splitItems = this.splitItemStacksSmart(lootTable, containerSize);
        // 2. 均匀分布到容器各个区域
        this.evenDistribution(container, splitItems, containerSize);
    }
    /**
     * 智能分裂物品堆叠 - 保持你的原始逻辑
     */
    splitItemStacksSmart(lootTable, containerSize) {
        const splitItems = [];
        for (const item of lootTable) {
            // 计算这个物品应该分裂的次数
            const splitCount = this.calculateSplitCount(item.amount, containerSize, lootTable.length);
            if (splitCount === 1) {
                // 不需要分裂，直接添加
                splitItems.push(item.clone());
            }
            else {
                // 进行分裂
                const splitStacks = this.splitStack(item, splitCount);
                splitItems.push(...splitStacks);
            }
        }
        return splitItems;
    }
    /**
     * 计算物品应该分裂的次数
     */
    calculateSplitCount(amount, containerSize, totalItems) {
        // 保留你的基础分裂策略
        if (amount <= 4)
            return 1;
        const availableSpace = containerSize - totalItems;
        if (amount <= 8) {
            return availableSpace > 5 ? 2 : 1;
        }
        else if (amount <= 16) {
            return availableSpace > 3 ? 2 : 1;
        }
        else {
            let splitCount = 2;
            let remaining = amount;
            while (remaining > 8 && splitCount < 4) {
                splitCount++;
                remaining = Math.ceil(remaining / 2);
            }
            return Math.min(splitCount, 4);
        }
    }
    /**
     * 随机分布分裂物品堆叠 - 保持你的Beta分布
     */
    splitStack(item, splitCount) {
        const stacks = [];
        let remainingAmount = item.amount;
        for (let i = 0; i < splitCount - 1; i++) {
            const splitAmount = this.randomDistribution(remainingAmount);
            const newItem = item.clone();
            newItem.amount = splitAmount;
            stacks.push(newItem);
            remainingAmount -= splitAmount;
        }
        const lastItem = item.clone();
        lastItem.amount = remainingAmount;
        stacks.push(lastItem);
        return stacks;
    }
    /**
     * 随机分布 - 保持你的原始实现
     */
    randomDistribution(amount) {
        if (amount <= 1)
            return 1;
        const alpha = 2;
        const beta = 2;
        const ratio = this.betaRandom(alpha, beta);
        const result = Math.round(amount * ratio);
        return Math.max(1, Math.min(amount - 1, result));
    }
    betaRandom(alpha, beta) {
        const gamma1 = this.gammaRandom(alpha, 1);
        const gamma2 = this.gammaRandom(beta, 1);
        return gamma1 / (gamma1 + gamma2);
    }
    gammaRandom(shape, scale) {
        if (shape < 1) {
            const u = Math.random();
            return this.gammaRandom(shape + 1, scale) * Math.pow(u, 1 / shape);
        }
        const d = shape - 1 / 3;
        const c = 1 / Math.sqrt(9 * d);
        let v;
        do {
            let x;
            do {
                x = this.normalRandom();
                v = 1 + c * x;
            } while (v <= 0);
            v = v * v * v;
            const u = Math.random();
            if (u < 1 - 0.0331 * (x * x) * (x * x) ||
                Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v))) {
                return scale * d * v;
            }
        } while (true);
    }
    normalRandom() {
        const u1 = Math.random();
        const u2 = Math.random();
        return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
    }
    /**
     * 均匀分布算法 - 确保物品分布在容器的各个区域
     */
    evenDistribution(container, items, containerSize) {
        // 计算容器布局（行数和列数）
        const { rows, columns } = this.getContainerLayout(containerSize);
        // 将物品分组到不同的区域
        const regionItems = this.distributeToRegions(items, rows, columns);
        // 在每个区域内随机放置物品
        this.placeInRegions(container, regionItems, rows, columns);
        // 可选：添加一些随机空槽位
        this.addStrategicEmptySlots(container, containerSize, items.length);
    }
    /**
     * 获取容器布局信息
     */
    getContainerLayout(containerSize) {
        if (containerSize === 54) {
            return { rows: 6, columns: 9 };
        }
        return { rows: 3, columns: 9 };
    }
    /**
     * 将物品分布到不同区域
     */
    distributeToRegions(items, rows, columns) {
        // 创建区域数组（每个区域是一个物品数组）
        const regions = Array.from({ length: rows }, () => []);
        // 洗牌物品
        const shuffledItems = this.shuffleArray([...items]);
        // 将物品轮流分配到各个区域
        shuffledItems.forEach((item, index) => {
            const regionIndex = index % rows;
            regions[regionIndex].push(item);
        });
        return regions;
    }
    /**
     * 在各个区域内放置物品
     */
    placeInRegions(container, regionItems, rows, columns) {
        regionItems.forEach((items, regionIndex) => {
            if (items.length === 0)
                return;
            // 计算该区域的起始槽位
            const startSlot = regionIndex * columns;
            const endSlot = startSlot + columns - 1;
            // 获取该区域的所有槽位并洗牌
            const regionSlots = this.shuffleArray(Array.from({ length: columns }, (_, i) => startSlot + i));
            // 在该区域内随机放置物品
            items.forEach((item, itemIndex) => {
                if (itemIndex < regionSlots.length) {
                    container.setItem(regionSlots[itemIndex], item);
                }
                // 如果物品数量超过区域槽位数，跳过多余的物品
            });
        });
    }
    /**
     * 添加战略性的空槽位
     */
    addStrategicEmptySlots(container, containerSize, itemCount) {
        // 只在物品数量较少时添加空槽位，避免过度稀疏
        if (itemCount > containerSize * 0.7)
            return;
        // 计算应该保留的空槽位数量
        const targetEmptySlots = Math.max(2, Math.floor(containerSize * 0.2));
        const currentEmptySlots = containerSize - itemCount;
        // 如果空槽位太少，随机清空一些
        if (currentEmptySlots < targetEmptySlots) {
            const slotsToEmpty = targetEmptySlots - currentEmptySlots;
            const allSlots = Array.from({ length: containerSize }, (_, i) => i);
            const shuffledSlots = this.shuffleArray(allSlots);
            let emptied = 0;
            for (const slot of shuffledSlots) {
                if (container.getItem(slot) && emptied < slotsToEmpty) {
                    container.setItem(slot);
                    emptied++;
                }
            }
        }
    }
    /**
     * 洗牌算法
     */
    shuffleArray(array) {
        const newArray = [...array];
        for (let i = newArray.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [newArray[i], newArray[j]] = [newArray[j], newArray[i]];
        }
        return newArray;
    }
}
// 应用伤害
export function applyDamage(entity, damage) {
    try {
        if (entity instanceof Player) {
            if (entity.getGameMode() === GameMode.Creative)
                return;
        }
        if (!entity.applyDamage(damage)) {
            const heal = entity.getComponent(EntityComponentTypes.Health);
            if (heal) {
                heal.setCurrentValue(heal.currentValue - damage < heal.effectiveMin ? heal.effectiveMin : heal.currentValue - damage);
            }
        }
    }
    catch (error) {
        console.error('应用伤害失败:', error);
    }
}
