import { EquipmentSlot, MinecraftDimensionTypes, system, world } from "@minecraft/server";
import { BPDynamicProperty, BPStaticProperty, portalBlasterIds } from "./portalBlaster";
import { calculateEuclideanDistance, getPlayerEquipment } from "blocky_portal/utils/my_API";
system.runInterval(() => {
    runCooldown();
    onTick();
}, 1);
system.runInterval(() => {
    tagHandling();
    guidebookAnimation();
    portalBlasterAnimation();
}, 5);
function guidebookAnimation() {
    const hasGuideBookInMainhand = "blocky_portal:hasGuideBookInMainhand";
    const players = world.getAllPlayers();
    players.forEach(player => {
        const equipment = getPlayerEquipment(player);
        const mainhand = equipment.getEquipment(EquipmentSlot.Mainhand);
        if (mainhand !== undefined) {
            if (mainhand.typeId === "blocky_portal:guidebook") {
                if (!player.hasTag(hasGuideBookInMainhand)) {
                    player.playAnimation('animation.blocky_portal.bracelet.arm', {
                        stopExpression: `query.equipped_item_any_tag('slot.weapon.mainhand', 'blocky_portal:guidebook') == false`
                    });
                    player.addTag(hasGuideBookInMainhand);
                }
            }
            else {
                if (player.hasTag(hasGuideBookInMainhand)) {
                    player.removeTag(hasGuideBookInMainhand);
                }
            }
        }
        else {
            if (player.hasTag(hasGuideBookInMainhand)) {
                player.removeTag(hasGuideBookInMainhand);
            }
        }
    });
}
const hasPortalBlasterInMainhand = "blocky_portal:hasPortalBlasterInMainhand";
function portalBlasterAnimation() {
    const players = world.getAllPlayers();
    players.forEach(player => {
        const equipment = getPlayerEquipment(player);
        const mainhand = equipment.getEquipment(EquipmentSlot.Mainhand);
        if (mainhand !== undefined) {
            if (portalBlasterIds.includes(mainhand.typeId)) {
                if (!player.hasTag(hasPortalBlasterInMainhand)) {
                    player.playAnimation('animation.blocky_portal.player.hold_blaster.', {
                        stopExpression: `query.equipped_item_any_tag('slot.weapon.mainhand', 'blocky_portal:portal_blaster') == false`
                    });
                    player.addTag(hasPortalBlasterInMainhand);
                }
            }
            else {
                if (player.hasTag(hasPortalBlasterInMainhand)) {
                    player.removeTag(hasPortalBlasterInMainhand);
                }
            }
        }
        else {
            if (player.hasTag(hasPortalBlasterInMainhand)) {
                player.removeTag(hasPortalBlasterInMainhand);
            }
        }
    });
}
const wasTeleportedTag = "blocky_portal:was_teleported";
function tagHandling() {
    const players = world.getAllPlayers();
    players.forEach(player => {
        if (!isOnCooldown(player)) {
            const lastPortalId = player.getDynamicProperty(BPDynamicProperty.lastPortalUsed);
            if (lastPortalId === undefined) {
                player.removeTag(wasTeleportedTag);
            }
            else {
                const lastPortal = world.getEntity(lastPortalId);
                if (lastPortal === undefined) {
                    player.removeTag(wasTeleportedTag);
                }
                else {
                    if (player.dimension.id !== lastPortal.dimension.id) {
                        player.removeTag(wasTeleportedTag);
                    }
                    else {
                        const distance = calculateEuclideanDistance(player.location, lastPortal.location);
                        if (distance >= 2) {
                            player.removeTag(wasTeleportedTag);
                        }
                    }
                }
            }
        }
    });
}
function runCooldown() {
    const objectiveId = "blocky_portal:cooldownTime";
    let scoreboard = world.scoreboard.getObjective(objectiveId);
    if (scoreboard === undefined) {
        scoreboard = world.scoreboard.addObjective(objectiveId, objectiveId);
    }
    scoreboard.getParticipants().forEach(participant => {
        let score = scoreboard.getScore(participant);
        score--;
        if (score < 0) {
            scoreboard.removeParticipant(participant);
        }
        else {
            scoreboard.setScore(participant, score);
        }
    });
}
function onTick() {
    let entities = [];
    entities = entities.concat(world.getDimension(MinecraftDimensionTypes.overworld).getEntities({ families: ["blocky_portal:portal"] }));
    entities = entities.concat(world.getDimension(MinecraftDimensionTypes.nether).getEntities({ families: ["blocky_portal:portal"] }));
    entities = entities.concat(world.getDimension(MinecraftDimensionTypes.theEnd).getEntities({ families: ["blocky_portal:portal"] }));
    //
    entities.forEach(portal => {
        const dualityPortalId = portal.getDynamicProperty(BPDynamicProperty.DualityPortalId);
        if (dualityPortalId === undefined) {
            return;
        }
        let dualPortal = world.getEntity(dualityPortalId);
        const isLinked = dualPortal !== undefined;
        portal.setProperty(BPStaticProperty.isLinked, isLinked);
        if (isLinked == false) {
            return;
        }
        //
        const entities = findEntitiesNearPortal(portal.dimension, portal.location, 1);
        if (entities.length > 0) {
            playScaleAnimation(portal);
            playScaleAnimation(dualPortal);
            entities.forEach(entity => {
                if (entity.typeId !== "minecraft:player") {
                    teleportEntityToLocation(dualPortal, entity);
                    activateCooldown(entity);
                }
            });
            const players = entities.filter(entity => entity.typeId === "minecraft:player");
            players.forEach(player => {
                playerUsePortal(portal, dualPortal, player);
            });
        }
    });
}
function playerUsePortal(portal, dualPortal, player) {
    const animation_length = 0.25;
    const tickDelay = animation_length * 20;
    const cooldown = 30 + tickDelay;
    activateCooldown(player, cooldown);
    player.setDynamicProperty(BPDynamicProperty.lastPortalUsed, dualPortal.id);
    player.addTag('blocky_portal:was_teleported');
    playInAnimation(portal, player);
    system.runTimeout(() => {
        teleportEntityToLocation(dualPortal, player);
        playOutAnimation(dualPortal, player);
        player.playSound('blocky.portal.portal.teleport');
    }, tickDelay);
}
function playScaleAnimation(portal) {
    portal.playAnimation('animation.blocky_portal.portal.scale');
}
function playInAnimation(portal, player) {
    const orientation = portal.getProperty(BPStaticProperty.orientation);
    let animations = [];
    switch (orientation) {
        case 0: {
            animations.push('animation.blocky_portal.player.side_in');
            break;
        }
        case 1: {
            animations.push('animation.blocky_portal.player.up_in');
            break;
        }
        case 2: {
            animations.push('animation.blocky_portal.player.down_in');
            break;
        }
    }
    animations.forEach(animation => {
        player.playAnimation(animation);
    });
}
function playOutAnimation(portal, player) {
    const orientation = portal.getProperty(BPStaticProperty.orientation);
    let animations = [];
    switch (orientation) {
        case 0: {
            animations.push('animation.blocky_portal.player.side_out');
            break;
        }
        case 1: {
            animations.push('animation.blocky_portal.player.up_out');
            break;
        }
        case 2: {
            animations.push('animation.blocky_portal.player.down_out');
            break;
        }
    }
    animations.forEach(animation => {
        player.playAnimation(animation);
    });
}
function isOnCooldown(entity) {
    const objectiveId = "blocky_portal:cooldownTime";
    let scoreboard = world.scoreboard.getObjective(objectiveId);
    if (scoreboard === undefined) {
        scoreboard = world.scoreboard.addObjective(objectiveId, objectiveId);
    }
    return scoreboard.hasParticipant(entity);
}
function activateCooldown(entity, ticks = 20) {
    const objectiveId = "blocky_portal:cooldownTime";
    let scoreboard = world.scoreboard.getObjective(objectiveId);
    if (scoreboard === undefined) {
        scoreboard = world.scoreboard.addObjective(objectiveId, objectiveId);
    }
    scoreboard.setScore(entity, ticks);
}
function findEntitiesNearPortal(dimension, location, radius) {
    const queryOptions = {
        location,
        maxDistance: radius,
        excludeFamilies: ["blocky_portal:portal", "blocky_portal:portal_projectile"]
    };
    return dimension.getEntities(queryOptions).filter(entity => {
        const teleporationConditions = !isOnCooldown(entity) && !entity.hasTag(wasTeleportedTag);
        return teleporationConditions;
    });
}
function teleportEntityToLocation(dualPortal, entity) {
    let orientation = dualPortal.getProperty(BPStaticProperty.orientation);
    let rotation = dualPortal.getProperty(BPStaticProperty.rotation);
    let ry = entity.getRotation().y;
    if (orientation == 0) {
        switch (rotation) {
            case 0: {
                ry = 0;
                break;
            }
            case 1: {
                ry = 90;
                break;
            }
            case 2: {
                ry = 180;
                break;
            }
            case 3: {
                ry = -90;
                break;
            }
        }
    }
    let entityLocation = dualPortal.location;
    if (orientation == 1) {
        entityLocation.y--;
    }
    entity.teleport(entityLocation, {
        dimension: dualPortal.dimension,
        rotation: {
            x: entity.getRotation().x,
            y: ry
        }
    });
}