import { BlockPermutation, world } from '@minecraft/server';
import createCircleBorderEffect from './circleBorder';
import ScriptingModule from '../scriptingModule';
import createWitherWraithPortalEffect from './witherWraithPortal';
import WBVector3 from '../util/wbVector3';
import { getRandomRange } from '../util/random';
const GROUP_RADIUS = 15;
const FOG_MAX_DISTANCE = 25;
const FOG_PARTICLES_PER_TICK = 2;
const FOG_MAX_VERTICAL_OFFSET = { min: -16, max: 8 };
const FOG_ALLOWED_BLOCK_PERMUTATIONS = new Set([
    BlockPermutation.resolve('twb_wisu:wilt_block'),
    BlockPermutation.resolve('twb_wisu:ash_layer', { 'twb_wisu:level': 7 }),
]);
const overworld = world.getDimension('overworld');
const rayOptions = {
    includeLiquidBlocks: true,
    includePassableBlocks: true,
    excludePermutations: [
        BlockPermutation.resolve('twb_wisu:wilt')
    ],
    maxDistance: FOG_MAX_VERTICAL_OFFSET.max - FOG_MAX_VERTICAL_OFFSET.min,
};
export default class EffectsModule extends ScriptingModule {
    constructor() {
        super('EffectsModule');
        this.clusters = [];
    }
    onInitialize() {
        this.addScriptEvent('twb_wisu:effect_circle_border', (e) => {
            const source = e.sourceEntity || e.sourceBlock;
            if (!source)
                return;
            const { dimension, location } = source;
            const params = e.message.split(' ');
            const radius = parseFloat(params[0]);
            const numSegments = parseInt(params[1], 10);
            createCircleBorderEffect({ dimension, ...location }, radius, numSegments);
        });
        this.addScriptEvent('twb_wisu:wither_wraith_portal', (e) => {
            const source = e.sourceEntity || e.sourceBlock;
            if (!source)
                return;
            const { dimension, location } = source;
            createWitherWraithPortalEffect({ dimension, ...location });
        });
        this.updateClusters();
    }
    onSecond() {
        this.updateClusters();
    }
    onTick() {
        this.spawnFogParticles();
    }
    /**
     * Create clusters of players that are close together
     */
    updateClusters() {
        const clusters = [];
        for (const player of world.getAllPlayers()) {
            // Skip players that are not in the overworld
            // eslint-disable-next-line no-continue
            if (player.dimension !== overworld)
                continue;
            // Find a group that is within range
            let foundCluster = false;
            for (const cluster of clusters) {
                const distance = WBVector3.distance(cluster.center, player.location);
                if (distance < GROUP_RADIUS) {
                    cluster.players.push(player);
                    cluster.center = cluster.players.reduce((c, p) => c.add(p.location), new WBVector3(0, 0, 0)).divide(cluster.players.length);
                    foundCluster = true;
                    break;
                }
            }
            // If no group was found, create a new one
            if (!foundCluster) {
                const cluster = {
                    players: [player],
                    center: WBVector3.fromMC(player.location)
                };
                clusters.push(cluster);
            }
        }
        this.clusters = clusters;
    }
    spawnFogParticles() {
        this.clusters.forEach((cluster) => {
            for (let i = 0; i < FOG_PARTICLES_PER_TICK; i++) {
                const location = cluster.center.add({
                    x: getRandomRange(-FOG_MAX_DISTANCE, FOG_MAX_DISTANCE),
                    y: FOG_MAX_VERTICAL_OFFSET.max,
                    z: getRandomRange(-FOG_MAX_DISTANCE, FOG_MAX_DISTANCE),
                });
                try {
                    const ray = overworld.getBlockFromRay(location, { x: 0, y: -1, z: 0 }, rayOptions);
                    if (ray && FOG_ALLOWED_BLOCK_PERMUTATIONS.has(ray.block.permutation)) {
                        overworld.spawnParticle('twb_wisu:ground_fog', new WBVector3(0.5, 1.0, 0.5).add(ray.block));
                    }
                }
                catch {
                    return;
                }
            }
        });
    }
}
