import { Block, ItemStack, Player, RawMessage, system, VanillaEntityIdentifier, Vector3, VectorXZ, world } from "@minecraft/server";
import { ChestLootConfig, ChestLootParamsType, count, EntityConfig, LuckyBlockEventCategory, LuckyBlockItemRange, RandomItemConfig, RandomItemParamsType, SetBlockConfig, SetBlockParamsType, SpawnEntityParamsType } from "../types/type";
import { getRandomByWeight, getRandomElements, getRandomEventCategory, spawnItem, normalizeCount, shuffle, randint, removeColor, getColor, getRandomXZOffset, getSpawnY } from "../types/function";
import { LuckyBlockEventName, LuckyBlockEventType, spawnLocationBlock } from "../types/enum";
import { chestLootEvent, RandomItemEvent, setBlockEvent, spawnEntityEvent } from "./luckyBlockEventConfig";
// 2025-9-26
// 只是完成一些基础框架和方便测试，后面慢慢优化
/**
 * 在这期间在完善功能，没有记录
 */
// 2025-10-2
// 完善了main函数

// 随机物品单独事件


// 定义幸运方块事件列表
const luckyBlockEventList: LuckyBlockEventCategory[] = [
    {
        eventName: LuckyBlockEventName.RandomItem,
        eventType: LuckyBlockEventType.lucky,
        weight: 1,
        events: RandomItemEvent,
    },
    {
        eventName: LuckyBlockEventName.ChestLoot,
        eventType: LuckyBlockEventType.lucky,
        weight: 1,
        events: chestLootEvent,
    },
    {
        eventName: LuckyBlockEventName.SpawnEntity,
        eventType: LuckyBlockEventType.lucky,
        weight: 1,
        events: spawnEntityEvent,
    }, {
        eventName: LuckyBlockEventName.Structure,
        eventType: LuckyBlockEventType.lucky,
        weight: 0,
        events: RandomItemEvent,// 占位中
    },
    {
        eventName: LuckyBlockEventName.SetBlock,
        eventType: LuckyBlockEventType.lucky,
        weight: 1234567,
        events: setBlockEvent,
    },
]

export function main(player: Player, block: Block, luckyValue: number): void {
    // debug
    lucky(player, block);
    return;
    if (luckyValue === 0) {
        // 我直接50%概率
        if (Math.random() < 0.5) {
            lucky(player, block);
            console.log('is lucky');
        } else {
            unLucky(player, block);
            console.log('is unLucky');

        }
        return;
    }

    const bonus = Math.floor(Math.random() * (luckyValue + 1));
    const totalRange = 100 + Math.abs(bonus);
    const luckyThreshold = 50 + bonus;
    const randomResult = Math.floor(Math.random() * totalRange);

    if (randomResult < luckyThreshold) {
        lucky(player, block);
        console.log('is lucky');

    } else {
        unLucky(player, block);
        console.log('is unLucky');
    }
}
// 幸运方块主函数
function lucky(player: Player, block: Block): void {
    // 随机获取一个事件分类，它的类型必须是幸运的
    const category = getRandomEventCategory(luckyBlockEventList.filter(c => c.eventType === LuckyBlockEventType.lucky));
    // 执行事件
    try {
        // 如果随机的是随机物品事件
        if (category?.eventName === LuckyBlockEventName.RandomItem) {
            // 随机获取一个事件
            const event = getRandomByWeight(category.events);
            // 执行事件
            if (event.RandomItemConfig?.itemTypeId) {
                const typeId = event.RandomItemConfig.itemTypeId;
                const randomItems = getRandomElements(typeId, normalizeCount(event.RandomItemConfig?.range?.amount));
                (event.event as RandomItemParamsType)(player, block, { range: event.RandomItemConfig?.range, itemTypeId: randomItems, isMixed: event.RandomItemConfig?.isMixed });
                return;
            }
        }
        // 如果随机的是箱子战利品事件
        if (category?.eventName === LuckyBlockEventName.ChestLoot) {
            // 随机获取一个事件
            const event = getRandomByWeight(category.events);
            // 执行事件
            if (event.ChestLootConfig?.lootlist) {
                const lootId = event.ChestLootConfig.lootlist;
                (event.event as ChestLootParamsType)(player, block, { lootlist: lootId });
                return;
            }
        }

        // 随机生成方块事件
        if (category?.eventName === LuckyBlockEventName.SetBlock) {
            // 随机获取一个事件
            const event = getRandomByWeight(category.events);
            // 执行事件
            if (event.SetBlockConfig?.isPillar) {
                const isPillar = event.SetBlockConfig.isPillar;
                (event.event as SetBlockParamsType)(player, block, {
                    isPillar: isPillar,
                    blockPillar: event.SetBlockConfig?.blockPillar,
                    options: event.SetBlockConfig?.options,
                });
                return;
            }
            if (event.SetBlockConfig?.blockTypeId) {
                const blockTypeId = event.SetBlockConfig.blockTypeId;
                (event.event as SetBlockParamsType)(player, block, {
                    blockTypeId: blockTypeId,
                    blockEvent: event.SetBlockConfig?.blockEvent,
                    options: event.SetBlockConfig?.options,
                });
                return;
            }
        }
        // 如果随机的是生成实体事件
        if (category?.eventName === LuckyBlockEventName.SpawnEntity) {
            // 随机获取一个事件
            const event = getRandomByWeight(category.events);
            // 执行事件
            if (event.EntityConfig?.spawn) {
                const spawn = event.EntityConfig.spawn;
                (event.event as SpawnEntityParamsType)(player, block, {
                    spawn: spawn,
                    setTime: event.EntityConfig?.setTime,
                });
                return;
            }
        }
    } catch (error) {
        console.error("幸运方块事件执行失败：" + error);
    }
}

function unLucky(player: Player, block: Block): void {
    // 随机一个事件分类，它的类型必须是厄运的
    // 随机获取一个事件分类，它的类型必须是厄运的
    const category = getRandomEventCategory(luckyBlockEventList.filter(c => c.eventType === LuckyBlockEventType.unLucky));
    // 执行事件
    try {
        // 占位中，什么都不做
    } catch (error) {
        console.error("厄运方块事件执行失败：" + error);
    }
}



class Options {
    player: Player

    constructor(player: Player) {
        this.player = player;
    }

    // 发送消息
    sendMessage(message: (RawMessage | string)[] | RawMessage | string | undefined, interval?: number): void {
        if (!message) return;
        if (interval) {
            system.runTimeout(() => {
                if (message) this.player.sendMessage(message);
            }, interval);
        } else {
            if (message) this.player.sendMessage(message);
        }
    }

    // 播放音效
    playSound(sound: string | undefined, interval?: number): void {
        if (!sound) return;
        if (interval) {
            system.runTimeout(() => {
                if (sound) this.player.playSound(sound);
            }, interval);
        } else {
            if (sound) this.player.playSound(sound);
        }
    }
}
// 随机物品
export function randomItem(player: Player, block: Block, params: RandomItemConfig): void {
    const { range, itemTypeId, isMixed } = params;

    // 生成随机物品
    const actualRange: LuckyBlockItemRange = range;

    const items = itemTypeId || [];
    if (isMixed) {
        const randomItem = getRandomElements(items, normalizeCount(actualRange.amount));
        for (const item of randomItem) {
            spawnItem(player.dimension.id, new ItemStack(item, normalizeCount(actualRange.count)), block.location);
        }
    } else {
        for (const item of items) {
            spawnItem(player.dimension.id, new ItemStack(item, normalizeCount(actualRange.count)), block.location);
        }
    }
}

// 生成箱子战利品
export function chestLoot(player: Player, block: Block, params: ChestLootConfig): void {

    const { lootlist } = params;
    const lootId = getRandomElements(lootlist, 1)[0];
    const getLootTable = world.getLootTableManager().getLootTable(lootId);

    if (!getLootTable) return;

    const generateLootFromTable = world.getLootTableManager().generateLootFromTable(getLootTable);

    if (!generateLootFromTable) return;
    for (const item of generateLootFromTable) {
        try {
            spawnItem(player.dimension.id, item, block.location);
        } catch (error) {
            console.error("生成箱子战利品失败：" + error);
        }
    }
}


// 生成方块柱子
export function setBlockPillar(player: Player, block: Block, params: SetBlockConfig): void {
    let { isPillar } = params;
    let { interval, message, sound } = params.options || {};
    const conversion = params.blockPillar?.conversion;
    const BlockEvent = params.blockEvent;
    let { hasLightning, onFire, location, probability } = BlockEvent || {};
    if (!location) location = spawnLocationBlock.block;
    const options = new Options(player);

    if (!isPillar || !params.blockPillar) {
        console.warn('不是方块柱子类型或者方块柱子配置缺失');
        return;
    }
    let { blockTypeIdList, topBlockTypeId, height, isShuffled } = params.blockPillar;

    if (!interval) interval = 0;
    if (interval) {
        interval = normalizeCount(interval);
    }


    if (!blockTypeIdList) return;
    if (!topBlockTypeId) {
        topBlockTypeId = ["minecraft:coal_block"]
    }
    options.playSound(sound);
    options.sendMessage(message);
    // 随机获取一个方块ID列表
    if (!height) {
        height = {
            max: 3,
            min: 3,
        }
    } else if (typeof height === 'number') {
        height = {
            max: height,
            min: height,
        }
    }

    // 获取起始高度
    const startHeight = params.blockPillar?.startHeight || 0;
    // 随机获取一个方块ID列表
    const newBlockTypeIdList = isShuffled ? shuffle(getRandomElements(blockTypeIdList, randint(height.min, height.max))) : getRandomElements(blockTypeIdList, randint(height.min, height.max));

    //是混泥土粉末
    const hasConcretePowder = newBlockTypeIdList.some(blockId => blockId.includes('concrete_powder'));

    // 按顺序设置方块，每个间隔 interval tick
    for (let i = 0; i < newBlockTypeIdList.length; i++) {
        const y = block.location.y + i + startHeight;

        system.runTimeout(() => {
            try {
                world.getDimension(block.dimension.id).setBlockType(
                    { x: block.location.x, y: y, z: block.location.z },
                    newBlockTypeIdList[i]
                );
                // 在最后一个的上面生成矿石块并生成闪电，然后检查是否可以转换
                if (i === newBlockTypeIdList.length - 1) {
                    system.runTimeout(() => {
                        world.getDimension(block.dimension.id).setBlockType(
                            { x: block.location.x, y: block.location.y + i + 1, z: block.location.z },
                            getRandomElements(shuffle(topBlockTypeId), 1)[0]
                        );
                        // 生成闪电
                        system.runTimeout(() => {
                            try {
                                /** 生成概率 默认100 */
                                probability = probability ?? 100;
                                if (randint(0, 100) <= probability) {
                                    // 生成闪电
                                    if (hasLightning) {
                                        if (location == spawnLocationBlock.block) {
                                            world.getDimension(block.dimension.id).runCommand(`summon lightning_bolt ${block.location.x + 0.5} ${block.location.y + i + 1} ${block.location.z + 0.5}`);
                                        } else if (location == spawnLocationBlock.player) {
                                            world.getDimension(block.dimension.id).runCommand(`summon lightning_bolt ${player.location.x + 0.5} ${player.location.y} ${player.location.z + 0.5}`);
                                        }
                                    }

                                    // 生成火
                                    if (onFire) {
                                        if (location == spawnLocationBlock.block) {
                                            world.getDimension(block.dimension.id).setBlockType(
                                                { x: block.location.x, y: block.location.y + i + 2, z: block.location.z },
                                                'minecraft:fire'
                                            )
                                        } else if (location == spawnLocationBlock.player) {
                                            world.getDimension(block.dimension.id).setBlockType(
                                                { x: player.location.x, y: player.location.y, z: player.location.z },
                                                'minecraft:fire'
                                            )
                                        }
                                    }
                                }

                                // 检查是否可以转换
                                if (conversion) {
                                    for (let i = 0; i < newBlockTypeIdList.length; i++) {
                                        const y = block.location.y + i + startHeight;

                                        // 获取当前位置的方块
                                        const currentBlock = world.getDimension(block.dimension.id).getBlock({
                                            x: block.location.x,
                                            y: block.location.y + i,
                                            z: block.location.z
                                        });

                                        if (currentBlock) {
                                            // 获取原方块的颜色
                                            const color = getColor(currentBlock.typeId);
                                            // 替换方块
                                            if (color) {
                                                world.getDimension(block.dimension.id).setBlockType(
                                                    { x: block.location.x, y: block.location.y + i, z: block.location.z },
                                                    `minecraft:${color}_${conversion}`
                                                );
                                            }
                                        }
                                    }
                                }
                            } catch (error) {

                                console.error("生成闪电、火焰、或者方块替换失败" + error);
                            }
                        }, 5);

                    }, hasConcretePowder ? interval * (startHeight + newBlockTypeIdList.length) / 5 : interval);
                }
            } catch (error) {
                console.error("设置方块柱子失败：" + error);
            }

        }, interval * i);
    }
}

// 设置方块
export function setBlock(player: Player, block: Block, params: SetBlockConfig): void {
    /**提取配置 */
    const { blockTypeId } = params;
    let { message, sound } = params.options || {};
    /** 间隔时间 默认0*/
    let interval = params.options?.interval || 0;
    /**方块事件 */
    const BlockEvent = params.blockEvent;
    let { hasLightning, onFire, location, probability } = BlockEvent || {};
    /**生成位置默认为方块位置 */
    if (!location) location = spawnLocationBlock.block;
    /** 选项 */
    const options = new Options(player);
    if (interval) {
        interval = normalizeCount(interval);
    }
    if (!blockTypeId) return;
    let newBlockTypeId: string;
    if (Array.isArray(blockTypeId)) {
        newBlockTypeId = blockTypeId[randint(0, blockTypeId.length - 1)]
    } else {
        newBlockTypeId = blockTypeId;
    }
    let newBlockItem = new ItemStack(newBlockTypeId)
    try {
        system.runTimeout(() => {
            world.getDimension(block.dimension.id).setBlockType(
                { x: block.location.x, y: block.location.y, z: block.location.z },
                newBlockTypeId
            );
            system.runTimeout(() => {
                /** 生成概率 默认100 */
                probability = probability ?? 100;
                if (randint(0, 100) <= probability) {
                    // 生成闪电
                    if (hasLightning) {
                        if (location == spawnLocationBlock.block) {
                            world.getDimension(block.dimension.id).runCommand(`summon lightning_bolt ${block.location.x + 0.5} ${block.location.y + 1} ${block.location.z + 0.5}`);
                        } else if (location == spawnLocationBlock.player) {
                            world.getDimension(block.dimension.id).runCommand(`summon lightning_bolt ${player.location.x + 0.5} ${player.location.y} ${player.location.z + 0.5}`);
                        }

                    }
                    // 生成火
                    if (onFire) {
                        if (location == spawnLocationBlock.block) {
                            world.getDimension(block.dimension.id).setBlockType(
                                { x: block.location.x, y: block.location.y + 1, z: block.location.z },
                                'minecraft:fire'
                            );
                        } else if (location == spawnLocationBlock.player) {
                            world.getDimension(block.dimension.id).setBlockType(player.location,
                                'minecraft:fire'
                            );
                        }
                    }
                }

            }, 5);
        }, interval);
    } catch (error) {
        console.error("生成闪电或者火焰失败" + error);
    }
    options.sendMessage(message?.replace('$blockname', newBlockItem.localizationKey), interval);
    options.playSound(sound, interval);
}

// 生成实体
export function spawnEntity(player: Player, block: Block, params: EntityConfig): void {
    // console.log('进入函数');

    let { setTime } = params;
    for (const spawn of params.spawn) {
        let { entityTypeId, offset, name, count, entityEffects, playerEffects } = spawn;
        let { message, sound } = spawn.options || {};
        let interval = spawn.options?.interval || 0;
        const options = new Options(player);
        if (interval) {
            interval = normalizeCount(interval);
        }
        count = normalizeCount(count) ?? 1
        if (!entityTypeId) return;

        try {
            system.runTimeout(() => {
                let x = block.location.x + 0.5;
                let z = block.location.z + 0.5;
                const offsetXZ = getRandomXZOffset(offset ?? 0);
                // 生成实体
                for (let i = 0; i < count; i++) {
                    const blockY = !offset || world.getDimension(block.dimension.id).getBlock({ x: x + offsetXZ.x, y: block.location.y, z: z + offsetXZ.z })?.typeId == 'minecraft:air' ? block.location.y : getSpawnY({ x: x + offsetXZ.x, y: block.location.y, z: z + offsetXZ.z }, block.dimension.id);
                    let entity = world.getDimension(block.dimension.id).spawnEntity(
                        entityTypeId as VanillaEntityIdentifier,
                        { x: x + offsetXZ.x, y: blockY, z: z + offsetXZ.z }
                    )
                    if (name) {
                        entity.nameTag = name;
                    }
                }
            }, interval);
        } catch (error) {
            console.error("生成实体失败：" + error);
        }
        options.sendMessage(message, interval);
        options.playSound(sound, interval);
    }
}

