import { world, system } from "@minecraft/server";
import * as utils from "./utils";
import * as Vector3 from "./vector3";

const Velocity = 1.5;
const FixedHeightOffset = 1.5; // Adjust this value to control how high the projectile is spawned from the ground

export async function onTick() {
    let skeletonKings = world.getDimension("overworld").getEntities({ type: "goe_bos:skeleton_king" });
    skeletonKings = skeletonKings.concat(world.getDimension("the_end").getEntities({ type: "goe_bos:skeleton_king" }));
    skeletonKings = skeletonKings.concat(world.getDimension("nether").getEntities({ type: "goe_bos:skeleton_king" }));

    skeletonKings.forEach(skeletonKing => {
        if (!skeletonKing.hasTag("goe_bos_using_special_attack"))
            return;
        skeletonKing.removeTag("goe_bos_using_special_attack");

        const skeletonKingLocation = new Vector3.Vector3(skeletonKing.location);
        let nearestPlayer = null;
        let nearestDistance = Infinity;

        skeletonKing.dimension.getPlayers().forEach(player => {
            const playerLocation = new Vector3.Vector3(player.location);
            const distance = Vector3.distance(skeletonKingLocation, playerLocation);
            if (distance < nearestDistance) {
                nearestDistance = distance;
                nearestPlayer = player;
            }
        });

        if (!nearestPlayer) return;

        // Calculate the direction to the nearest player using Vector3 utility functions
        const directionToPlayer = Vector3.getDirection(skeletonKingLocation, new Vector3.Vector3(nearestPlayer.location));

        // Set a fixed height for the projectile
        const projectileSpawn = new Vector3.Vector3({
            x: skeletonKingLocation.x + directionToPlayer.x * 2,
            y: skeletonKingLocation.y + FixedHeightOffset, // Fixed height offset from the skeleton's position
            z: skeletonKingLocation.z + directionToPlayer.z * 2
        });
        
        let projectile = undefined;
        try {
            projectile = skeletonKing.dimension.spawnEntity("goe_bos:slash_projectile", {
                x: projectileSpawn.x, 
                y: projectileSpawn.y, 
                z: projectileSpawn.z
            });
        } catch (error) {
            utils.debug("Failed to summon the slash_projectile projectile");
            return;
        }

        const projectileVelocity = new Vector3.Vector3(directionToPlayer).multiply(Velocity);

        const summonCommand = `summon goe_bos:slash ${skeletonKingLocation.x} ${skeletonKingLocation.y + FixedHeightOffset} ${skeletonKingLocation.z} facing ${nearestPlayer.location.x} ${nearestPlayer.location.y} ${nearestPlayer.location.z}`;
        try {
            skeletonKing.dimension.runCommand(summonCommand);
        } catch (error) {
            // console.error("Failed to summon the slash_projectile projectile:", error);
            return;
        }

        const dummy = skeletonKing.dimension.getEntities({
            type: "goe_bos:slash",
            location: skeletonKingLocation,
            maxDistance: 5
        })[0];

        projectile.applyImpulse({
            x: projectileVelocity.x, 
            y: projectileVelocity.y, 
            z: projectileVelocity.z
        });

        let inc = 1;

        const runId = system.runInterval(() => {
            if (!dummy || !dummy.isValid()) {
                system.clearRun(runId);
                return;
            }
            if (!projectile || !projectile.isValid()) {
                system.clearRun(runId);
                return;
            }

            const projectileLocation = projectile.location;
            const updatedFacingLocation = {
                x: projectileLocation.x + directionToPlayer.x,
                y: projectileSpawn.y, // Maintain the same height throughout the movement
                z: projectileLocation.z + directionToPlayer.z
            };

            dummy.teleport({ x: projectileLocation.x, y: projectileSpawn.y, z: projectileLocation.z }, {
                facingLocation: updatedFacingLocation
            });

            if (inc > 100) {
                system.clearRun(runId);
            }
            inc++;
        }, 1);
    });
}
