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

const BossFightMusic = new Map([
    [
        "pixell_bbo:ares",
        {
            music: {
                name: "pixell_bbo.bg.ares",
                startDistance: 32,
                stopDistance: 64,
            },
        },
    ],
    [
        "pixell_bbo:hades",
        {
            music: {
                name: "pixell_bbo.bg.hades",
                startDistance: 32,
                stopDistance: 64,
            },
        },
    ],
    [
        "pixell_bbo:unknown",
        {
            music: {
                name: "pixell_bbo.bg.unknown",
                startDistance: 32,
                stopDistance: 64,
            },
        },
    ],
    [
        "pixell_bbo:craterus",
        {
            music: {
                name: "pixell_bbo.bg.craterus",
                startDistance: 32,
                stopDistance: 64,
            },
        },
    ],
    [
        "pixell_bbo:burazazu",
        {
            music: {
                name: "pixell_bbo.bg.burazazu",
                startDistance: 32,
                stopDistance: 64,
            },
        },
    ],
    [
        "pixell_bbo:sweetgabriel",
        {
            music: {
                name: "pixell_bbo.bg.sweet_gabriel",
                startDistance: 32,
                stopDistance: 64,
            },
        },
    ],
]);

const musicTriggerEvent = "pixell_bbo:boss_fight_music";
const musicPropertyName = "pixell_bbo:boss_music_playing";
const musicSourceId = "pixell_bbo:boss_music_source";

const showLogMessage = false;

world.afterEvents.dataDrivenEntityTrigger.subscribe((event) => {
    const { entity, eventId } = event;

    if (!entity) return;

    system
        .waitTicks(10)
        .then(() => {
            /**
             * @type {import("@minecraft/server").EntityQueryOptions}
             */
            const filter = {
                families: ["boss"],
            };

            if (entity && entity?.matches(filter)) {
                const musicData = BossFightMusic.get(entity.typeId);

                if (!musicData) return;

                const {
                    music: { name, startDistance, stopDistance },
                } = musicData;

                switch (eventId) {
                    case musicTriggerEvent: {
                        const playersInside = entity?.dimension?.getPlayers({
                            location: entity.location,
                            maxDistance: startDistance,
                        });

                        const playersOutside = entity?.dimension?.getPlayers({
                            location: entity.location,
                            minDistance: startDistance,
                            maxDistance: stopDistance,
                        });

                        for (let player of playersInside) {
                            /**
                             * @type {boolean}
                             */
                            const isMusicPlaying =
                                player.getDynamicProperty(musicPropertyName) ?? false;

                            /**
                             * @type {string}
                             */
                            const musicSource = player.getDynamicProperty(musicSourceId) ?? "";

                            player.setDynamicProperty(musicSourceId, entity.id);

                            if (!isMusicPlaying) {
                                player.setDynamicProperty(musicPropertyName, true);

                                player.stopMusic();

                                player.playMusic(name, {
                                    loop: true,
                                });

                                if (showLogMessage) {
                                    console.warn(`${player.name} is inside range`);
                                }
                            }

                            continue;
                        }

                        for (let player of playersOutside) {
                            /**
                             * @type {boolean}
                             */
                            const isMusicPlaying =
                                player.getDynamicProperty(musicPropertyName) ?? false;

                            /**
                             * @type {string}
                             */
                            const musicSource = player.getDynamicProperty(musicSourceId) ?? "";

                            if (!isMusicPlaying) continue;

                            if (musicSource === entity.id) {
                                player.setDynamicProperty(musicPropertyName, false);

                                player.stopMusic();
                            }

                            if (showLogMessage) {
                                console.warn(`${player.name} is outside range`);
                            }
                        }

                        break;
                    }

                    default: {
                        break;
                    }
                }
            }
        })
        .catch((e) => {});
});

world.afterEvents.entityDie.subscribe((event) => {
   

   
});

world.beforeEvents.entityRemove.subscribe((event) => {
    const { removedEntity } = event;

    const entity = removedEntity;

    if (!entity) return;

    const location = entity?.location;
    const dimension = entity?.dimension;

    if (!location || !dimension) return;

    const musicData = BossFightMusic.has(entity.typeId);

    if (!musicData) return;

    system
        .waitTicks(20)
        .then(() => {
            const players = dimension.getPlayers({
                location: location,
                maxDistance: 64,
            });

            for (let player of players) {
                /**
                 * @type {boolean}
                 */
                const isMusicPlaying = player.getDynamicProperty(musicPropertyName) ?? false;

                if (!isMusicPlaying) continue;

                player.setDynamicProperty(musicPropertyName, false);

                player.stopMusic();
            }
        })
        .catch((e) => {
            console.error(e);
        });
});

world.afterEvents.playerDimensionChange.subscribe((event) => {
    const { player } = event;

    /**
     * @type {boolean}
     */
    const isMusicPlaying = player.getDynamicProperty(musicPropertyName) ?? false;

    if (!isMusicPlaying) return;

    player.setDynamicProperty(musicPropertyName, false);

    player.stopMusic();
});
