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

const boomerangs= [
    {name: "pu_sg:diamond_boomerang", projectile: "pu_sg:diamond_boomerang_projectile", damage: 5},
    {name: "pu_sg:gold_boomerang", projectile: "pu_sg:gold_boomerang_projectile", damage: 3},
    {name: "pu_sg:iron_boomerang", projectile: "pu_sg:iron_boomerang_projectile", damage: 4},
    {name: "pu_sg:netherite_boomerang", projectile: "pu_sg:netherite_boomerang_projectile", damage: 6},
    {name: "pu_sg:stone_boomerang", projectile: "pu_sg:stone_boomerang_projectile", damage: 4},
    {name: "pu_sg:wooden_boomerang", projectile: "pu_sg:wooden_boomerang_projectile", damage: 3},
];

function getBoomerang(projectile) {
    for (const boomerang of boomerangs) {
        if (boomerang.projectile === projectile) {
            return boomerang;
        }
    }
    return null;
}

export async function onItemUse(event) {
    const player = event.source;
    const item = event.itemStack;
    if (item && item.typeId.endsWith("_boomerang")) {
        player.setDynamicProperty("pu_sg_boomerang_durability", item.getComponent("minecraft:durability").damage);
        utils.runPlayerCommand(player, "playsound pu_sg:boomerang_throw @a[r=7] ~ ~ ~");  
    }
}

export async function onEntitySpawn(event) {
    const entity = event.entity;
    if (entity.typeId.endsWith("_boomerang_projectile")) {
        const player = entity.dimension.getPlayers({ location: entity.location, maxDistance: 10 })[0];
        if (player) {
            launchBoomerang(player, entity);
        }
    }
}

const BOOMERANG_LIFETIME = 30; // Ticks before it starts returning
const RETURN_DISTANCE = 5; // Distance at which the boomerang returns to the player’s hand
const BLOCK_HIT_RADIUS = 5; // Radius to detect block collisions

function distance3D(pos1, pos2) {
    return Math.sqrt(
        (pos1.x - pos2.x) ** 2 +
        (pos1.y - pos2.y) ** 2 +
        (pos1.z - pos2.z) ** 2
    );
}

const RETURN_SPEED = 0.1; // Slightly faster return speed for more direct control
const ARC_RADIUS = 0.25; // Reduced arc radius for tighter return curve
const VERTICAL_OSCILLATION = 0.15; // Smaller vertical movement for a controlled return arc
const HEIGHT_OFFSET = 1; // Lower height offset for a smoother return path
const FALL_GRAVITY = -0.1; // Lower height offset for a smoother return path


function launchBoomerang(player, boomerangEntity) {
    let ticks = 0;
    let isReturning = false; // Flag to control the return state
    let falling = false; // Flag to trigger falling after collision

    const rang = getBoomerang(boomerangEntity.typeId);
    if (!rang) return;

    const interval = system.runInterval(() => {
        ticks++;
        if (!boomerangEntity.isValid()) {
            system.clearRun(interval);
            return;
        }
        if (!player.isValid()) {
            boomerangEntity.remove();
            system.clearRun(interval);
            return;
        }

        // Monitor and adjust velocity for upward throws
        try {
            const velocity = boomerangEntity.getVelocity();
            if (velocity.y > 1) { 
                boomerangEntity.applyImpulse({ x: 0, y: -0.05, z: 0 });
            }
        } catch (error) {
        }

        const blockPos = {
            x: Math.floor(boomerangEntity.location.x),
            y: Math.floor(boomerangEntity.location.y + BLOCK_HIT_RADIUS),
            z: Math.floor(boomerangEntity.location.z)
        };

        const block = boomerangEntity.dimension.getBlock(blockPos);
        if (!falling && block && block.typeId !== "minecraft:air") {
            isReturning = false;
            falling = true;
        }

        if (falling) {
            const rangLocation = boomerangEntity.location;
            boomerangEntity.applyImpulse({ x: 0, y: FALL_GRAVITY, z: 0 });
            const boomerangItem = new ItemStack(rang.name);
            const durability = player.getDynamicProperty("pu_sg_boomerang_durability");
            if (durability < (boomerangItem.getComponent("minecraft:durability").maxDurability - 1)) {
                boomerangItem.getComponent("minecraft:durability").damage = durability + 1;
                player.dimension.spawnItem(boomerangItem, { x: rangLocation.x, y: rangLocation.y + 1.5, z: rangLocation.z });
            } else {
                player.playSound('random.break');
            }
            boomerangEntity.remove();
            system.clearRun(interval);
            return;
        }

        // Detect collisions and handle damage
        const entitiesInRange = boomerangEntity.dimension.getEntities({
            location: boomerangEntity.location,
            maxDistance: 1,
        });
        for (const entity of entitiesInRange) {
            if (entity.typeId === "minecraft:item") continue;
            if (!entity || !entity.isValid() || entity === player) continue;
            entity.applyDamage(rang.damage, { damagingEntity: player, cause: EntityDamageCause.contact });
        }

        if (!isReturning && ticks >= BOOMERANG_LIFETIME) {
            isReturning = true;
        }

        if (isReturning) {
            const playerPos = player.location;
            const boomerangPos = boomerangEntity.location;
            const distance = distance3D(playerPos, boomerangPos);

            if (distance <= RETURN_DISTANCE) {
                const boomerangItem = new ItemStack(rang.name);
                const durability = player.getDynamicProperty("pu_sg_boomerang_durability");
                if (durability < (boomerangItem.getComponent("minecraft:durability").maxDurability - 1)) {
                    boomerangItem.getComponent("minecraft:durability").damage = durability + 1;
                    player.dimension.spawnItem(boomerangItem, { x: playerPos.x, y: playerPos.y + 1.5, z: playerPos.z });
                } else {
                    player.playSound('random.break');
                }
                boomerangEntity.remove();
                system.clearRun(interval);
            } else {
                const directionX = playerPos.x - boomerangPos.x;
                const directionY = (playerPos.y + 1.5 + HEIGHT_OFFSET) - boomerangPos.y;
                const directionZ = playerPos.z - boomerangPos.z;

                const angle = ticks * 0.05;
                const leftOffsetX = ARC_RADIUS * Math.cos(angle);
                const leftOffsetZ = -ARC_RADIUS * Math.sin(angle);

                const magnitude = Math.sqrt(directionX ** 2 + directionY ** 2 + directionZ ** 2);
                const x_angle = (directionX / magnitude) + leftOffsetX;
                const y_angle = (directionY / magnitude) + Math.sin(ticks * 0.05) * VERTICAL_OSCILLATION;
                const z_angle = (directionZ / magnitude) + leftOffsetZ;

                boomerangEntity.applyImpulse({
                    x: RETURN_SPEED * x_angle,
                    y: RETURN_SPEED * y_angle,
                    z: RETURN_SPEED * z_angle
                });
            }
        }
    }, 1);
}

