import { world, system, EasingType, InvalidEntityError, Player, Entity, EntityRideableComponent } from "@minecraft/server";
import { GeneralUtils } from "../utils.js"

/**
 * @param {EntityLoadAfterEvent} event - The event to use
 */
export const groundHandleEntityLoad = (event) => {
    const entity = event.entity;
    if (entity.getDynamicProperty("animation.spinning")) {
        entity.playAnimation("brake");
        entity.setDynamicProperty("animation.spinning", false);
    }
}

/**
 * @param {Entity} groundEntity - The entity to use for the tick
 * @param {EntityRideableComponent} rideableComponent - The rideable component
 * @param {Dimension} dimension - The dimension the vehicle is in
 */
export const groundEntityTick = (groundEntity, rideableComponent, dimension) => {
    const rider = rideableComponent.getRiders()[rideableComponent.controllingSeat];
    const player_rider = GeneralUtils.world.getPlayerFromEntity(rider);

    const input = player_rider ? player_rider.inputInfo.getMovementVector() : { x: 0, y: 0 };

    const trails = groundEntity.getProperty("af:trails");
    const width = groundEntity.getProperty("af:trails.width") ?? 4;

    const reverseModifier = (groundEntity.getProperty("af:vehicle.reverse_modifier") ?? 5) / 10;

    const transmission = groundEntity.getProperty("af:vehicle.transmission");
    if (!transmission) return;

    let dir = groundEntity.getDynamicProperty("direction") ?? groundEntity.getRotation().y;
    let old_dir = dir;

    const speed = groundEntity.getComponent("movement")?.currentValue ?? 0.2;

    let waterSpeed = groundEntity.isInWater * -0.5 + 1;
    if (groundEntity.hasComponent("minecraft:underwater_movement")) {
        if (groundEntity.isInWater) {
            waterSpeed = groundEntity.getComponent("minecraft:underwater_movement").currentValue
        } else {
            waterSpeed = 1
        }
    }

    const reverseMod = input.y < 0 ? reverseModifier : 1;

    const velocity = { x: Math.sin(dir) * input.y * reverseMod * speed * waterSpeed, y: 0, z: Math.cos(dir) * input.y * reverseMod * speed * waterSpeed };

    if (groundEntity.isOnGround) {
        groundEntity.applyImpulse(velocity);
    }

    const rotSpeed = groundEntity.getProperty("af:vehicle.rotation-speed") ?? 40;

    const isReversing = input.y < 0 ? -1 : 1;
    if (transmission === "mono") {
        dir += GeneralUtils.math.toRad(rotSpeed / 20) * input.x * input.y * reverseMod
    };
    if (transmission === "dual") {
        dir += GeneralUtils.math.toRad(rotSpeed / 20) * input.x * isReversing
    };

    const endDeadzone = groundEntity.getProperty("af:body-turret.end-deadzone") ?? 20
    var turretPitch = groundEntity.getDynamicProperty("turret-pitch") ?? 0;

    if (endDeadzone >= 0) {
        turretPitch = GeneralUtils.math.clamp(turretPitch, -endDeadzone, endDeadzone);
    }

    turretPitch = GeneralUtils.math.toRad(turretPitch);

    groundEntity.setDynamicProperty("direction", dir);

    groundEntity.lookAt({
        x: groundEntity.location.x + Math.sin(dir) * 100,
        y: groundEntity.location.y - Math.sin(turretPitch) * 100,
        z: groundEntity.location.z + Math.cos(dir) * 100
    });

    const spinning = groundEntity.getDynamicProperty("animation.spinning");

    if (transmission === "dual") {
        if (input.x !== 0 && input.y === 0) {
            groundEntity.triggerEvent("af:is_moving");
        }
        if (input.x !== 0 && input.y === 0 && !spinning) {
            groundEntity.playAnimation("move");
            groundEntity.setDynamicProperty("animation.spinning", true);
            system.runTimeout(() => {
                groundEntity.setDynamicProperty("animation.spinning", false);
            }, 20)
        }
        if (input.x === 0 && input.y === 0 && spinning) {
            groundEntity.playAnimation("brake");
            groundEntity.setDynamicProperty("animation.spinning", false);
        }
    }

    const offset = width / 2;
    const rot = groundEntity.getRotation().y;

    [-1, 1].forEach(i => {
        const block = dimension.getBlock({ x: groundEntity.location.x + Math.sin(rot) * offset * i, y: groundEntity.location.y - 1, z: groundEntity.location.z + Math.cos(rot) * offset * i });
        if (block?.matches("grass_block")) block.setType("dirt");
    });

    if (trails === "heavy") {
        const half = Math.floor((width + 1) / 2);
        for (let x = -half; x <= half; x++) {
            for (let z = -half; z <= half; z++) {
                const block = dimension.getBlock({ x: groundEntity.location.x + x, y: groundEntity.location.y - 1, z: groundEntity.location.z + z });
                if (block?.matches("ice")) block.setType("frosted_ice");
            }
        }
    }

    groundEntity.setDynamicProperty("turret_drag", old_dir - dir);
}