import * as mc from "@minecraft/server";
import * as utils from "../utils/index";
import { HeartAbilityManager } from "../systems/index";
const INVALID_BLOCKS = [
    "minecraft:bedrock",
    "minecraft:barrier",
    "minecraft:end_portal",
    "minecraft:end_portal_frame",
];
export async function silverfishAbility(player) {
    var _a;
    utils.mclog(`silverfish`);
    const startBlock = player.dimension.getBlockFromRay(player.getHeadLocation(), utils.Vector3.UP);
    if (!startBlock) {
        player.sendMessage(utils.translate("error.silverfish_heart.no_blocks"));
        return;
    }
    if (startBlock) {
        const target = await getDestination(player);
        if (target && target.y - player.location.y > 2 && player.isValid()) {
            HeartAbilityManager.addInvulnerability(player, "noDamage");
            const cachedRotation = player.getRotation();
            utils.mclog(`Set destination to ${target}, ${target.y - player.location.y} blocks above ${player.nameTag}`, "silverfish");
            player.inputPermissions.setPermissionCategory(mc.InputPermissionCategory.Movement, false);
            player.inputPermissions.setPermissionCategory(mc.InputPermissionCategory.Camera, false);
            player.inputPermissions.setPermissionCategory(mc.InputPermissionCategory.Jump, false);
            player.teleport(target, { rotation: { x: -90, y: 0 } });
            player.camera.fade({ fadeColor: { red: 0, green: 0, blue: 0 }, fadeTime: { fadeInTime: 0.0, holdTime: 0.25, fadeOutTime: 0.25 } });
            const effectBox = utils.spawnEntitySafe(player.dimension, "ldz:silverfish_ascend", player.location);
            await utils.waitForTicks(1);
            player.playSoundAt("ability.silverfish.say");
            player.playSound("ability.silverfish.ascend");
            player.spawnParticle("ldz:silverfish_ability", player.location.up(3));
            effectBox.playAnimation("animation.silverfish_ascend.show", { players: [player.nameTag] });
            player.playAnimation("animation.player.silverfish.swim", { controller: "silverfish_ascend" });
            player.camera.setCamera("minecraft:free", { location: player.location.add(4), facingLocation: player.getHeadLocation() });
            await utils.waitForTicks(70);
            player.camera.fade({ fadeColor: { red: 0.7, green: 0.7, blue: 0.7 }, fadeTime: { fadeInTime: 0.25, holdTime: 0.5, fadeOutTime: 0.25 } });
            await utils.waitForTicks(10);
            player.inputPermissions.setPermissionCategory(mc.InputPermissionCategory.Movement, true);
            player.inputPermissions.setPermissionCategory(mc.InputPermissionCategory.Camera, true);
            player.inputPermissions.setPermissionCategory(mc.InputPermissionCategory.Jump, true);
            player.teleport(target, { rotation: cachedRotation });
            player.playSoundAt("ability.silverfish.say");
            player.camera.clear();
            effectBox.remove();
            HeartAbilityManager.removeInvulnerability(player, "noDamage");
            return;
        }
        utils.mcwarn(`Failed ${player.nameTag} to get destination ${target} or not enough height: ${((_a = target === null || target === void 0 ? void 0 : target.y) !== null && _a !== void 0 ? _a : player.location.y) - player.location.y} < 3`);
        player.sendMessage(utils.translate("error.silverfish_heart.invalid"));
        return;
    }
    utils.mcwarn(`Failed ${player.nameTag} to get start block`);
    player.sendMessage(utils.translate("error.silverfish_heart.no_blocks"));
}
function getDestination(player) {
    return new Promise(resolve => {
        const origin = player.location.center();
        let cachedDestination = undefined;
        let currentLocation = new utils.Vector3({ x: origin.x, y: player.dimension.heightRange.max, z: origin.z });
        function* iterate() {
            var _a, _b;
            do {
                yield;
                const newBlock = player.dimension.getTopmostBlock(origin, currentLocation.y - 1);
                if (!newBlock) {
                    utils.mcerror(`No blocks found above ${origin}`);
                    break;
                }
                currentLocation = new utils.Vector3(newBlock.location);
                utils.mclog(`Processing height ${currentLocation.y}`, "silverfish");
                if (INVALID_BLOCKS.includes(newBlock.typeId)) {
                    utils.mclog(`Skipping height ${currentLocation.y} due to invalid block ${newBlock.typeId}`, "silverfish");
                    continue;
                }
                const footBlock = (_a = player.dimension.getBlock(currentLocation.up(1))) === null || _a === void 0 ? void 0 : _a.isAir;
                const headBlock = (_b = player.dimension.getBlock(currentLocation.up(2))) === null || _b === void 0 ? void 0 : _b.isAir;
                if (!footBlock || !headBlock) {
                    utils.mclog(`Skipping height ${currentLocation.y} due to not enough room`, "silverfish");
                    continue;
                }
                if (currentLocation.y < origin.y + 2) {
                    utils.mclog(`Stopping before height ${currentLocation.y} due to being too low`, "silverfish");
                    break;
                }
                utils.mclog(`Successfully found surface at ${currentLocation.y}`, "silverfish");
                cachedDestination = currentLocation;
            } while (currentLocation.y > origin.y + 2);
            resolve(cachedDestination === undefined ? undefined : cachedDestination.center().up());
        }
        mc.system.runJob(iterate());
    });
}
