import * as mc from "@minecraft/server";
import { waitForLoopEvent } from "./events";
import { mclog } from "./log";
import { Vector3 } from "./vector3";
/**
 * @remarks A script based version of our levitation/slow fall based flight method
 */
export class FlightSystem {
    get canDescend() {
        if (this.shiftDescend) {
            return this.pilot.isSneaking;
        }
        else {
            return true;
        }
    }
    /**
     * @remarks Creates a new flight system
     * @param data The options for the flight system
     * @example
     * Dragon Example
     * ```typescript
     * function rideDragon(player: SafetyCheckedPlayer, dragon: SafetyCheckedEntity) {
     *     dragon.addTag('victim');
     *     player.runCommand(`ride @s start_riding @e[type=${dragon.typeId},tag=${GlobalNamespace.Namespace}victim] teleport_rider if_group_fits`);
     *     dragon.removeTag('victim');
     *
     *     new FlightSystem({pilot: player, flyer: dragon, cancelCondition(pilot, flyer) {
     *         return !flyer.hasTag('hasRider');
     *     }});
     * }
     * ```
     * @example
     * Jetpack Example
     * ```typescript
     * function playerJetpack(player: utils.SafetyCheckedPlayer) {
     *     new utils.FlightSystem({pilot: player, flyer: player, shiftDescend: true, cancelCondition(pilot, flyer) {
     *         const equipment = player.getComponent(mc.EntityEquippableComponent.componentId) as mc.EntityEquippableComponent;
     *         return equipment.getEquipment(mc.EquipmentSlot.Chest)?.typeId !== 'ldz:jetpack';
     *     }});
     * }
     * ```
     */
    constructor(data) {
        this.pilot = data.pilot;
        this.flyer = data.flyer;
        this.shiftDescend = Boolean(data.shiftDescend);
        this.cancelCondition = data.cancelCondition;
        mclog(`Started ${this.pilot.name}'s Flight`);
        waitForLoopEvent(0, () => {
            this.flightHandler();
            if (this.cancelCondition(this.pilot, this.flyer) || !this.pilot.isValid() || !this.flyer.isValid()) {
                mclog(`Finished ${this.pilot.name}'s Flight`);
                return true;
            }
            else {
                return false;
            }
        });
    }
    flightHandler() {
        const x_rotation = this.pilot.getRotation().x;
        switch (true) {
            case this.pilot.isJumping && x_rotation <= -7:
                return this.rise();
            case this.pilot.isJumping:
                return this.lift();
            case x_rotation < 10:
                return this.glide();
            case x_rotation > 10 && x_rotation < 40 && this.canDescend:
                return this.descend();
            case this.canDescend:
                return this.dive();
            default:
                return this.glide();
        }
    }
    rise() {
        this.flyer.addEffect('levitation', 5, { amplifier: 12, showParticles: false });
    }
    lift() {
        this.flyer.addEffect('levitation', 5, { amplifier: 10, showParticles: false });
    }
    glide() {
        this.flyer.addEffect('slow_falling', 5, { amplifier: 255, showParticles: false });
        if (mc.system.currentTick % 5 === 0 && !this.flyer.isOnGround) {
            this.flyer.addEffect('levitation', 5, { amplifier: 0, showParticles: false });
        }
    }
    descend() {
        this.flyer.addEffect('slow_falling', 5, { amplifier: 1, showParticles: false });
    }
    dive() {
        const hit = this.flyer.dimension.getBlockFromRay(this.flyer.location, Vector3.DOWN, { maxDistance: 8 });
        if (!hit) {
            this.flyer.removeEffect('slow_falling');
        }
        else {
            this.flyer.addEffect('slow_falling', 5, { amplifier: 0, showParticles: false });
        }
    }
}
