import { Server } from "../../../libs/Core/index.js";
import { Dimension, Entity, system, world } from "@minecraft/server";
import EventWrappers from "../../utils/AfterEvents.js";


Server.scriptEventManager.registerEvent('void_beast_jump_attack', (e) => {
    //if (e.sourceEntity.typeId !== 'plank_waao:void_beast') return;

    let directionVector = e.sourceEntity.getViewDirection()
    // multiply direction vector by magnitude
    const impulse = 3.5;
    const finalVector = {
        x: directionVector.x * impulse,
        y: 0.7,
        z: directionVector.z * impulse
    };

    e.sourceEntity.applyImpulse(finalVector);
});



Server.scriptEventManager.registerEvent('void_beast_spawn_second_phase_mobs', (e) => {
    if (e.sourceEntity.typeId !== 'plank_waao:void_beast') return;

    const duration = 35;
    const mobCount = 15;

    system.runTimeout(() => {
        spawnSecondPhaseMobs(mobCount, duration, e.sourceEntity);
        system.runTimeout(() => { e.sourceEntity.triggerEvent('plank_waao:t.second_phase'); }, duration);
    }, 20);

    // const entity = dimension.spawnEntity(getRandomMob(), spawnLocation);
    // entity.addTag('plank_waao:summoned_by_void_beast');


});

/**
 * @param {number} mobCount
 * @param {number} duration
 * @param {Entity} entity 
 */
async function spawnSecondPhaseMobs(mobCount, duration, entity) {
    const d = entity.dimension;

    const intervals = getSpawnTimings(duration, mobCount);
    const locArr = findValidLocations(entity, mobCount);
    spawnRNGMobs(d, intervals, locArr);
}

/**
 * @param {number} duration - ticks 
 * @param {number} n - number of instances
 * @returns {number[]} - intervals
 */
function getSpawnTimings(duration, n) {
    const intervals = [];
    const interval = duration / n;
    let timeRemaining = duration;

    for (let i = 0; i < n; i++) {
        const randomDelay = Math.random() * interval;

        intervals.push(duration - timeRemaining + randomDelay)
        timeRemaining -= interval;
    }

    return intervals;
}

/**
 * 
 * @param {Dimension} dimension 
 * @param {number[]} intervals
 * @param {{x: number, y: number, z: number}[]} locationArr
 */
function spawnRNGMobs(dimension, intervals, locationArr) {
    const mobs = [
        'plank_waao:sculk_bug_adult',
        'plank_waao:sculk_pillbug',
        'plank_waao:sculker_mine'
    ];

    const getRandomMob = () => mobs[Math.floor(Math.random() * mobs.length)];
    for (const location of locationArr) {
        system.runTimeout(() => {
            dimension.spawnEntity(getRandomMob(), location)
                .addTag('plank_waao:summoned_by_void_beast');
        }, intervals.shift());
    }
}

/**
 * @param {Entity} boss 
 * @param {number} locations
 * @returns {{x: number, y: number, z: number}[]}
 */
function findValidLocations(boss, locations) {
    const rngLocationOffset = () => Math.floor(Math.random() * 17) - 8;
    const initialLocation = boss.location;
    const dimension = boss.dimension;

    const isValidLocation = (x, y, z) => {
        const blockLocation = { x, y, z };
        const block = dimension.getBlock(blockLocation);
        return block.isAir && block.above().isAir && !block.below().isAir;
    };

    const locationArr = [];

    while (locationArr.length < locations) {
        let attempts = 0;
        let locationFound = false;

        while (attempts < 10 && !locationFound) {
            const x = initialLocation.x + rngLocationOffset();
            const z = initialLocation.z + rngLocationOffset();
            const yOffsets = [0, -1, -2, -3, 1, 2, 3];

            for (const yOffset of yOffsets) {
                const y = initialLocation.y + yOffset;
                if (isValidLocation(x, y, z)) {
                    locationArr.push({ x, y, z });
                    locationFound = true;
                    break;
                }
            }

            attempts++;
        }

        if (!locationFound) {
            locationArr.push(initialLocation);
        }
    }

    return locationArr;
}


// handle resetting the invulnerable event on load
EventWrappers.LoadAfterEvent.registerEvent('plank_waao:void_beast', (e) => {
    if (!e.entity.isValid()) return;
    if (e.entity.getProperty('plank_waao:phase') == 1) e.entity.triggerEvent('plank_waao:t.setup_second_phase');
});