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


/**
 * @param {Player} player - The player to clear the camera of
 */
export const clearPlayerCameraTick = (player) => {
    // player will have the "minecraft:riding" component if they are riding something
    if (player.hasComponent("minecraft:riding")) {
        // add the "clear_camera_on_exit" tag to be ready for when the player doesn't have the riding component
        player.addTag("clear_camera_on_exit")
    }
    // if the player isn't riding and they have the "clear_camera_on_exit" tag that means they just dismounted what they were previously riding
    if (!player.hasComponent("minecraft:riding") && player.hasTag("clear_camera_on_exit")) {
        player.camera.clear()
        // clear camera for next 10 ticks to prevent camera issues
        system.runTimeout(() => {
            player.removeTag("clear_camera_on_exit")
        }, 10)
    }
}

/**
 * @param {Entity} entity - The entity to add custom cameras to children
 * @param {EntityRideableComponent} rideable_component - The rideable component to use
 * @param {{easeTime: number, easeType: EasingType}} easeOptions - The ease options to use for custom cameras
 */
export const addCustomCameras = (
    entity,
    rideable_component,
    easeOptions = {
        easeTime: 0.2,
        easeType: EasingType.InOutCirc
    }
) => {
    // ----- Read Properties -----
    const distance = entity.getProperty("af:camera.distance");
    const heightOffset = (entity.getProperty("af:camera.height-offest") ?? 0) + 3;
    const lookEndDeadzoneY = entity.getProperty("af:camera.look-end-deadzone-y") ?? 40;
    const lookEndDeadzoneX = entity.getProperty("af:camera.look-end-deadzone-x") ?? -1;
    const easeTime = entity.getProperty("af:camera.ease-time");

    // means the entity has no camera and can be skipped over
    if (!distance) return;

    if (easeTime) {
        easeOptions.easeTime = easeTime / 10;
    }

    for (const rider of rideable_component.getRiders()) {
        world.getPlayers().forEach(player => {
            if (rider.id == player.id) {
                let facingLocation = entity.location;

                const playerRotation = player.getRotation();

                let yaw = GeneralUtils.math.toRad(playerRotation.y);
                if (lookEndDeadzoneX >= 0) {
                    yaw = GeneralUtils.math.toRad(GeneralUtils.math.clamp(playerRotation.y, -lookEndDeadzoneX, lookEndDeadzoneX));
                }

                let pitch = GeneralUtils.math.toRad(playerRotation.x + heightOffset);
                if (lookEndDeadzoneY >= 0) {
                    pitch = GeneralUtils.math.toRad(GeneralUtils.math.clamp(playerRotation.x, -lookEndDeadzoneY, lookEndDeadzoneY) + heightOffset);
                }

                const turretId = entity.getDynamicProperty("turret_id");
                if (turretId) {
                    const turret = world.getEntity(turretId)
                    if (turret) {
                        facingLocation = {
                            x: turret.location.x + (-Math.sin(yaw) * Math.cos(pitch)) * 10000,
                            y: (turret.location.y + (-Math.sin(pitch)) * 10000) + heightOffset,
                            z: turret.location.z + (Math.cos(yaw) * Math.cos(pitch)) * 10000
                        }
                    }
                }

                if (entity.getProperty("af:plane.speed")) {
                    easeOptions = {
                        easeTime: 0.6,
                        easeType: EasingType.OutSine
                    }
                }

                const velocity = entity.getVelocity();

                facingLocation = {
                    x: facingLocation.x + velocity.x,
                    y: facingLocation.y + velocity.y,
                    z: facingLocation.z + velocity.z
                }

                player.camera.setCamera("minecraft:free", {
                    easeOptions: easeOptions,
                    location: GeneralUtils.math.vectors.calculateOrbitPosition(player.location, pitch + 0.1, yaw, distance, heightOffset),
                    facingLocation: facingLocation
                });
            }
        })
    }
}