import { system, world } from "@minecraft/server";

const DIMENSIONS = ["overworld", "nether", "the_end"];

const toRad = deg => deg * Math.PI / 180
const toDeg = rad => rad * 180 / Math.PI

world.afterEvents.dataDrivenEntityTrigger.subscribe(eventTriggerEvent => {
    const entity = eventTriggerEvent.entity;

    if (eventTriggerEvent.eventId === "af:GM_fired") {
        for (const name of DIMENSIONS) {
            const dimension = world.getDimension(name);
            const entities = dimension.getEntities();

            for (const tank_entity of entities) {
                if (tank_entity.getDynamicProperty("turret_id") === entity.id) {
                    if (tank_entity.hasComponent("rideable")) {
                        const rideable = tank_entity.getComponent("rideable");
                        const rider = rideable.getRiders()[rideable.controllingSeat];

                        if (rider?.isValid) {
                            const turretDir = entity.getRotation();

                            const pitchRad = toRad(turretDir.x);
                            const yawRad = toRad(turretDir.y);

                            const forward = {
                                x: -Math.sin(yawRad) * Math.cos(pitchRad),
                                y: -Math.sin(pitchRad),
                                z: Math.cos(yawRad) * Math.cos(pitchRad)
                            };

                            const spawnPos = {
                                x: entity.location.x + forward.x * 2,
                                y: entity.location.y + 2 + forward.y * 2,
                                z: entity.location.z + forward.z * 2
                            };

                            const missile = dimension.spawnEntity("af:guided_missile", spawnPos, { initialPersistence: true });
                            missile.setRotation(turretDir);

                            rider.setDynamicProperty("guided_missile", missile.id);
                            rider.setDynamicProperty("tank_turret", entity.id);
                        }
                    }
                }
            }
        }
    }
});

system.runInterval(() => {
    for (const name of DIMENSIONS) {
        const dimension = world.getDimension(name);
        const entities = dimension.getEntities();

        for (const entity of entities) {
            if (!entity) return;
            const missileId = entity.getDynamicProperty("guided_missile");
            if (!missileId) continue;

            const missile = world.getEntity(missileId);
            if (!missile) {
                entity.setDynamicProperty("guided_missile", undefined);

                const turretId = entity.getDynamicProperty("tank_turret");
                if (turretId) {
                    const turret = world.getEntity(turretId);
                    turret?.removeTag("GM_fired");
                }
                continue;
            }

            const rot = entity.getRotation();
            const yawDeg = rot.y;
            const pitchDeg = rot.x;

            const yawRad = toRad(yawDeg);
            const pitchRad = toRad(pitchDeg);

            const dx = -Math.sin(yawRad) * Math.cos(pitchRad);
            const dy = -Math.sin(pitchRad);
            const dz = Math.cos(yawRad) * Math.cos(pitchRad);

            const target = {
                x: entity.location.x + dx * 32,
                y: entity.location.y + dy * 32,
                z: entity.location.z + dz * 32
            };

            missile.lookAt(target);

            const missileRot = missile.getRotation();
            const missileYaw = toRad(missileRot.y);
            const missilePitch = toRad(missileRot.x);

            const vx = -Math.sin(missileYaw) * Math.cos(missilePitch);
            const vy = -Math.sin(missilePitch);
            const vz = Math.cos(missileYaw) * Math.cos(missilePitch);

            const missileSpeed = (missile.getProperty("af:missile.speed") ?? 5) * 0.1;

            missile.clearVelocity();
            missile.applyImpulse({
                x: vx * missileSpeed,
                y: vy * missileSpeed,
                z: vz * missileSpeed
            });

            const checkLocation = {
                x: missile.location.x + vx * 2,
                y: missile.location.y + vy * 2,
                z: missile.location.z + vz * 2
            }

            if (missile.dimension.getBlock(checkLocation).isSolid) {
                explode_missile(missile.dimension, missile.location, missile);
            }

            if (Math.sqrt(((missile.location.x - entity.location.x) ** 2) + ((missile.location.y - entity.location.y) ** 2) + ((missile.location.z - entity.location.z) ** 2)) >= 16) {
                explode_missile(missile.dimension, missile.location, missile)
            }
        }
    }
}, 1);


function explode_missile(dimension, location, entity) {
    dimension.createExplosion(location, 10, {
        breaksBlocks: true,
        source: entity,
        allowUnderwater: true,
        causesFire: true
    })

    entity.remove()
}