import BiomeObserver from "./BiomeObserver";
import { biomeParticleData } from "../consts/biomeParticles";
import { Player, system, Entity, world, EntityLoadAfterEvent, PlayerSpawnAfterEvent } from "@minecraft/server";

class BiomeParticleSystem {
    /** @type {Map<Player, {entity: Entity, biome: string, handler: number}>} */
    #playerData = new Map();

    constructor() {
        BiomeObserver.subscribeToBiomeChange(this.#setupPlayerEntityLink.bind(this));
        world.afterEvents.entityLoad.subscribe(this.#removeParticleEntity.bind(this));
    }

    /**
     * 
     * @param {EntityLoadAfterEvent} e 
     */
    #removeParticleEntity(e) {

        if (e.entity.typeId === 'ecbl_bc:particle_emitter') e.entity.remove();
    }

    /**
     * 
     * @param {Player} player 
     * @param {*} biome 
     */
    #setupPlayerEntityLink(player, biome) {
        this.#deletePlayerData(player);

        if (biome === 'vanilla') return;

        const entity = player.dimension.spawnEntity('ecbl_bc:particle_emitter', { ...player.location, y: player.location.y + 10 });
        if (biome !== 'vanilla') entity.triggerEvent(`ecbl_bc:set_biome_${biome}`);
        const handler = system.runInterval(() => {
            try {
                const data = this.#playerData.get(player);
                if (!data || data.handler !== handler) {
                    system.clearRun(handler);
                    return;
                }

                if (!entity?.isValid() || !player?.isValid()) {
                    this.#deletePlayerData(player);
                    system.clearRun(handler);
                    return;
                }

                entity.clearVelocity();
                entity.teleport({ ...player.location, y: player.location.y + 10 });
            } catch {
                system.clearRun(handler);
                this.#deletePlayerData(player);
            }
        });

        this.#playerData.set(player, { entity, biome, handler });
    }

    #deletePlayerData(player) {
        if (!this.#playerData.has(player)) return;

        const { entity, handler } = this.#playerData.get(player);
        this.#playerData.delete(player);

        system.clearRun(handler);
        if (entity?.isValid()) {
            entity.remove();
        }
    }
}

export default new BiomeParticleSystem();