import { Direction, Player, World, system, world } from "@minecraft/server";
import FSDynamicProperty from "../fs/libs/FSDynamicProperty";
import EntityManager from "../EntityManager";
import FSUtil from "../fs/FSUtil";
import FSInventoryManager from "../fs/libs/FSInventoryManager";
import FSMath from "../fs/FSMath";
import FSLocalizedString from "../fs/FSLocalizedString";
import FSPlayer from "../fs/FSPlayer";
import { LASER_CONSOLE_DISTANCE } from "../fs/FSConstants";
export default class LaserBeam {
    static tick(entity) {
        try {
            if (entity.typeId === "57d_sbunk:laser_wall_floor") {
                const width = 4;
                const dimension = entity.dimension;
                for (let i = 0; i < width; i++) {
                    const spawnLocation = EntityManager.getLocationOffsetByRotation(entity, -i, 0, 0);
                    dimension.spawnEntity("57d_sbunk:laser_floor", spawnLocation);
                }
                LaserBeam.onKilled(entity);
                entity.remove();
            }
            if (FSDynamicProperty.getBoolean(entity, "open")) {
                return;
            }
            const knockback_tag = FSUtil.namespacedStringCr("laserwall_back");
            const knockback_vertical_strengh = 0.15;
            const knockback_horizontal_strengh = 1;
            const length = entity.getProperty("property:fs_sbunk_laser_length") - 1;
            const direction = entity.getProperty("property:fs_sbunk_laser_direction");
            if (entity.typeId === "57d_sbunk:laser_floor") {
                let eqo = {
                    location: FSMath.add(entity.location, { x: 0.5, y: 0, z: 0 }),
                    volume: { x: 0, y: length, z: 0 }
                };
                entity.dimension.getPlayers(eqo).forEach(player => {
                    player.applyKnockback(1, 0, knockback_horizontal_strengh, knockback_vertical_strengh);
                    player.playSound("random.fuse");
                    player.playSound("random.hurt");
                    player.applyDamage(1);
                });
                entity.dimension.getEntities(eqo).forEach(entity => {
                    entity.addTag(knockback_tag);
                    entity.applyKnockback(1, 0, knockback_horizontal_strengh, knockback_vertical_strengh);
                    entity.applyDamage(1);
                });
                eqo = {
                    location: FSMath.add(entity.location, { x: -0.5, y: 0, z: 0 }),
                    volume: { x: 0, y: length, z: 0 }
                };
                entity.dimension.getPlayers(eqo).forEach(player => {
                    player.applyKnockback(-1, 0, knockback_horizontal_strengh, knockback_vertical_strengh);
                    player.playSound("random.fuse");
                    player.playSound("random.hurt");
                    player.applyDamage(1);
                });
                entity.dimension.getEntities(eqo).forEach(entity => {
                    entity.addTag(knockback_tag);
                    entity.applyKnockback(-1, 0, knockback_horizontal_strengh, knockback_vertical_strengh);
                    entity.applyDamage(1);
                });
                eqo = {
                    location: FSMath.add(entity.location, { x: 0, y: 0, z: 0.5 }),
                    volume: { x: 0, y: length, z: 0 }
                };
                entity.dimension.getPlayers(eqo).forEach(player => {
                    player.applyKnockback(0, 1, knockback_horizontal_strengh, knockback_vertical_strengh);
                    player.playSound("random.fuse");
                    player.playSound("random.hurt");
                    player.applyDamage(1);
                });
                entity.dimension.getEntities(eqo).forEach(entity => {
                    entity.addTag(knockback_tag);
                    entity.applyKnockback(0, 1, knockback_horizontal_strengh, knockback_vertical_strengh);
                    entity.applyDamage(1);
                });
                eqo = {
                    location: FSMath.add(entity.location, { x: 0, y: 0, z: -0.5 }),
                    volume: { x: 0, y: length, z: 0 }
                };
                entity.dimension.getPlayers(eqo).forEach(player => {
                    player.applyKnockback(0, -1, knockback_horizontal_strengh, knockback_vertical_strengh);
                    player.playSound("random.fuse");
                    player.playSound("random.hurt");
                    player.applyDamage(1);
                });
                entity.dimension.getEntities(eqo).forEach(entity => {
                    entity.addTag(knockback_tag);
                    entity.applyKnockback(0, -1, knockback_horizontal_strengh, knockback_vertical_strengh);
                    entity.applyDamage(1);
                });
            }
            if (entity.typeId === "57d_sbunk:laser_wall") {
                let volume = { x: 0, y: 0, z: 0 };
                let location = { x: 0, y: 0, z: 0 };
                let knockback_direction_x = 0;
                let knockback_direction_z = 0;
                switch (direction) {
                    case Direction.North:
                        volume = { x: -0.25, y: 1, z: -(length - 1) };
                        location = { x: 0.5, y: 0.25, z: -1 };
                        knockback_direction_x = 1;
                        knockback_direction_z = 0;
                        break;
                    case Direction.South:
                        volume = { x: -0.25, y: 1, z: length - 1 };
                        location = { x: 0.5, y: 0.25, z: 0 };
                        knockback_direction_x = 1;
                        knockback_direction_z = 0;
                        break;
                    case Direction.West:
                        volume = { x: -(length - 1), y: 1, z: 0.25 };
                        location = { x: -1, y: 0.25, z: -0.25 };
                        knockback_direction_x = 0;
                        knockback_direction_z = 1;
                        break;
                    case Direction.East:
                        volume = { x: length - 1, y: 1, z: 0.25 };
                        location = { x: 0, y: 0.25, z: -0.25 };
                        knockback_direction_x = 0;
                        knockback_direction_z = 1;
                        break;
                }
                let eqo = {
                    location: FSMath.add(entity.location, location),
                    volume: volume,
                    excludeTags: [knockback_tag]
                };
                entity.dimension.getPlayers(eqo).forEach(player => {
                    player.addTag(knockback_tag);
                    player.applyKnockback(knockback_direction_x, knockback_direction_z, knockback_horizontal_strengh, knockback_vertical_strengh);
                    player.playSound("random.fuse");
                    player.playSound("random.hurt");
                    player.applyDamage(1);
                });
                entity.dimension.getEntities(eqo).forEach(entity => {
                    entity.addTag(knockback_tag);
                    entity.applyKnockback(knockback_direction_x, knockback_direction_z, knockback_horizontal_strengh, knockback_vertical_strengh);
                    entity.applyDamage(1);
                });
                switch (direction) {
                    case Direction.North:
                        volume = { x: 0.25, y: 1, z: -(length - 1) };
                        location = { x: -0.5, y: 0.25, z: -1 };
                        knockback_direction_x = -1;
                        knockback_direction_z = 0;
                        break;
                    case Direction.South:
                        volume = { x: 0.25, y: 1, z: length - 1 };
                        location = { x: -0.5, y: 0.25, z: 0 };
                        knockback_direction_x = -1;
                        knockback_direction_z = 0;
                        break;
                    case Direction.West:
                        volume = { x: -(length - 1), y: 1, z: -0.25 };
                        location = { x: -1, y: 0.25, z: -0.5 };
                        knockback_direction_x = 0;
                        knockback_direction_z = -1;
                        break;
                    case Direction.East:
                        volume = { x: length - 1, y: 1, z: -0.25 };
                        location = { x: 0, y: 0.25, z: -0.5 };
                        knockback_direction_x = 0;
                        knockback_direction_z = -1;
                        break;
                }
                eqo = {
                    location: FSMath.add(entity.location, location),
                    volume: volume,
                    excludeTags: [knockback_tag]
                };
                entity.dimension.getPlayers(eqo).forEach(player => {
                    player.addTag(knockback_tag);
                    player.applyKnockback(knockback_direction_x, knockback_direction_z, knockback_horizontal_strengh, knockback_vertical_strengh);
                    player.playSound("random.fuse");
                    player.playSound("random.hurt");
                    player.applyDamage(1);
                });
                entity.dimension.getEntities(eqo).forEach(entity => {
                    entity.addTag(knockback_tag);
                    entity.applyKnockback(knockback_direction_x, knockback_direction_z, knockback_horizontal_strengh, knockback_vertical_strengh);
                    entity.applyDamage(1);
                });
                eqo = {
                    tags: [knockback_tag]
                };
                entity.dimension.getPlayers(eqo).forEach(player => {
                    player.removeTag(knockback_tag);
                });
                entity.dimension.getEntities(eqo).forEach(entity => {
                    entity.removeTag(knockback_tag);
                });
            }
        }
        catch (error) { }
    }
    static calcAngleDegrees(x, y) {
        return (Math.atan2(y, x) * 180) / Math.PI;
    }
    static angleBetweenTwoEntities(entity1, entity2) {
        var p1 = {
            x: entity1.location.x,
            z: entity1.location.z
        };
        var p2 = {
            x: entity2.location.x,
            z: entity2.location.z
        };
        return (Math.atan2(p2.z - p1.z, p2.x - p1.x) * 180) / Math.PI;
    }
    static init(entity) {
        FSDynamicProperty.setBoolean(entity, "open", false);
        let command = "fill ^ ^ ^ ^-3 ^3 ^0 barrier [] replace air []";
        entity.runCommand(command);
    }
    static calculateHeight(entity) {
        if (!entity.isValid()) {
            return -1;
        }
        LaserBeam.onOpen(entity);
        const dimension = entity.dimension;
        let rco = {
            maxDistance: 6,
            includeLiquidBlocks: false,
            includePassableBlocks: false
        };
        let length = 0;
        let raycast_hit = dimension.getBlockFromRay(entity.location, { x: 0, y: 1, z: 0 }, rco);
        if (raycast_hit && raycast_hit.block) {
            length = Math.round(raycast_hit.block.location.y - entity.location.y);
        }
        if (length <= 0) {
            length = 6;
        }
        entity.triggerEvent(`fs:set_length_${length}`);
        LaserBeam.onClose(entity);
        return length;
    }
    static calculateWidth(entity) {
        if (!entity.isValid()) {
            return -1;
        }
        LaserBeam.onOpen(entity);
        const dimension = entity.dimension;
        let rco = {
            maxDistance: 6,
            includeLiquidBlocks: false,
            includePassableBlocks: false
        };
        let raycastDirection = { x: 0, y: 0, z: 0 };
        const direction = entity.getProperty("property:fs_sbunk_laser_direction");
        switch (direction) {
            case Direction.North:
                raycastDirection = { x: 0, y: 0, z: -1 };
                break;
            case Direction.South:
                raycastDirection = { x: 0, y: 0, z: 1 };
                break;
            case Direction.West:
                raycastDirection = { x: -1, y: 0, z: 0 };
                break;
            case Direction.East:
                raycastDirection = { x: 1, y: 0, z: 0 };
                break;
        }
        let length = 0;
        const location = FSMath.add(entity.location, { x: 0, y: 0.5, z: 0 });
        let raycast_hit = dimension.getBlockFromRay(location, raycastDirection, rco);
        if (raycast_hit && raycast_hit.block) {
            switch (direction) {
                case Direction.North:
                    length = Math.round(entity.location.z - 0.5 - raycast_hit.block.location.z);
                    break;
                case Direction.South:
                    length = Math.round(raycast_hit.block.location.z - entity.location.z);
                    break;
                case Direction.West:
                    length = Math.round(entity.location.x - 0.5 - raycast_hit.block.location.x);
                    break;
                case Direction.East:
                    length = Math.round(raycast_hit.block.location.x - entity.location.x);
                    break;
            }
        }
        if (length <= 0) {
            length = 6;
        }
        entity.triggerEvent(`fs:length_${length}`);
        LaserBeam.onClose(entity);
        return length;
    }
    static onEnable(entity) {
        LaserBeam.onClose(entity);
        entity.removeTag(FSUtil.namespacedStringCr("disabled"));
        entity.setProperty("property:fs_sbunk_laser_enabled", true);
    }
    static onDisable(entity) {
        LaserBeam.onOpen(entity);
        entity.addTag(FSUtil.namespacedStringCr("disabled"));
        entity.setProperty("property:fs_sbunk_laser_enabled", false);
    }
    static onOpen(entity) {
        const wso = {
            volume: 0.05,
            pitch: 1
        };
        const length = entity.getProperty("property:fs_sbunk_laser_length") - 1;
        const direction = entity.getProperty("property:fs_sbunk_laser_direction");
        if (entity.typeId === "57d_sbunk:laser_wall") {
            let command = `fill ^ ^ ^ ^ ^ ^ air [] replace barrier []`;
            switch (direction) {
                case Direction.North:
                    command = `fill ^ ^ ^ ^ ^ ^${-length} air [] replace barrier []`;
                    break;
                case Direction.South:
                    command = `fill ^ ^ ^ ^ ^ ^${length} air [] replace barrier []`;
                    break;
                case Direction.West:
                    command = `fill ^ ^ ^ ^${-length} ^ ^ air [] replace barrier []`;
                    break;
                case Direction.East:
                    command = `fill ^ ^ ^ ^${length} ^ ^ air [] replace barrier []`;
                    break;
            }
            entity.teleport(entity.location);
            entity.runCommand(command);
            EntityManager.playAnimation(entity, "open");
            world.playSound("fs.sbunk.laser_down", entity.location, wso);
            FSDynamicProperty.setBoolean(entity, "open", true);
            return;
        }
        if (entity.typeId === "57d_sbunk:laser_floor") {
            const command = `fill ^ ^ ^ ^ ^${length} ^ air [] replace barrier []`;
            entity.teleport(entity.location);
            entity.runCommand(command);
            EntityManager.playAnimation(entity, "open");
            world.playSound("fs.sbunk.laser_down", entity.location, wso);
            FSDynamicProperty.setBoolean(entity, "open", true);
            return;
        }
    }
    static onClose(entity) {
        const wso = {
            volume: 0.05,
            pitch: 1
        };
        const length = entity.getProperty("property:fs_sbunk_laser_length") - 1;
        const direction = entity.getProperty("property:fs_sbunk_laser_direction");
        const hasSeenLaserConsoleMessage = FSDynamicProperty.getBoolean(world, "hasSeenLaserConsoleMessage");
        if (!hasSeenLaserConsoleMessage) {
            LaserBeam.outputLaserBeamRequiresLaserConsoleMessage(entity, world);
            FSDynamicProperty.setBoolean(world, "hasSeenLaserConsoleMessage", true);
        }
        if (entity.typeId === "57d_sbunk:laser_wall") {
            entity.triggerEvent("fs:remove_physics");
            entity.teleport(entity.location);
            EntityManager.playAnimation(entity, "close");
            world.playSound("fs.sbunk.laser_up", entity.location, wso);
            FSDynamicProperty.setBoolean(entity, "open", false);
            return;
        }
        if (entity.typeId === "57d_sbunk:laser_floor") {
            entity.triggerEvent("fs:remove_physics");
            entity.teleport(entity.location);
            EntityManager.playAnimation(entity, "close");
            world.playSound("fs.sbunk.laser_up", entity.location, wso);
            FSDynamicProperty.setBoolean(entity, "open", false);
            return;
        }
    }
    static onKilled(entity) {
        let length = 3;
        const location = entity.location;
        const loc0 = EntityManager.getLocationOffsetByRotation(entity, 0, 0, 0);
        const loc1 = EntityManager.getLocationOffsetByRotation(entity, -3, length, 0);
        let command = `/fill ${loc0.x} ${loc0.y} ${loc0.z} ${loc1.x} ${loc1.y} ${loc1.z} air [] replace barrier []`;
        if (entity.typeId === "57d_sbunk:laser_floor") {
            length = entity.getProperty("property:fs_sbunk_laser_length") - 1;
            command = `/fill ${location.x} ${location.y} ${location.z} ${location.x} ${location.y + length} ${location.z} air [] replace barrier []`;
        }
        if (entity.typeId === "57d_sbunk:laser_wall") {
            length = entity.getProperty("property:fs_sbunk_laser_length") - 1;
            const direction = entity.getProperty("property:fs_sbunk_laser_direction");
            command = `/fill ${location.x} ${location.y} ${location.z} ${location.x} ${location.y} ${location.z} air [] replace barrier []`;
            switch (direction) {
                case Direction.North:
                    command = `/fill ${location.x} ${location.y} ${location.z} ${location.x} ${location.y} ${location.z - length} air [] replace barrier []`;
                    break;
                case Direction.South:
                    command = `/fill ${location.x} ${location.y} ${location.z} ${location.x} ${location.y} ${location.z + length} air [] replace barrier []`;
                    break;
                case Direction.West:
                    command = `/fill ${location.x} ${location.y} ${location.z} ${location.x - length} ${location.y} ${location.z} air [] replace barrier []`;
                    break;
                case Direction.East:
                    command = `/fill ${location.x} ${location.y} ${location.z} ${location.x + length} ${location.y} ${location.z} air [] replace barrier []`;
                    break;
            }
        }
        const dimenion = entity.dimension;
        system.run(() => {
            dimenion.runCommand(command);
        });
    }
    static onItemUsed(player, item) {
        if (item === "57d_sbunk:laser_wall") {
            const location = player.getHeadLocation();
            const direction = player.getViewDirection();
            const dimension = player.dimension;
            const rco = {
                maxDistance: 8,
                includeLiquidBlocks: true,
                includePassableBlocks: true
            };
            const raycast_hit = dimension.getBlockFromRay(location, direction, rco);
            if (raycast_hit && raycast_hit.block) {
                const block = raycast_hit.block;
                const face = raycast_hit.face;
                if (face === Direction.Up || face === Direction.Down) {
                    player.playSound("fs.sbunk.chat_ping");
                    player.sendMessage({ translate: FSLocalizedString.localize("chat.laser_beam.place_on_wall", "§c[!] You must place the laser beam on a wall", "Laser beam not placed on the wall warning message") });
                    return;
                }
                let adjacentBlock = undefined;
                switch (face) {
                    case Direction.North:
                        adjacentBlock = block.north(1);
                        break;
                    case Direction.South:
                        adjacentBlock = block.south(1);
                        break;
                    case Direction.West:
                        adjacentBlock = block.west(1);
                        break;
                    case Direction.East:
                        adjacentBlock = block.east(1);
                        break;
                }
                if (adjacentBlock && adjacentBlock.permutation.matches("minecraft:air")) {
                    const spawn_location = adjacentBlock.bottomCenter();
                    const entity = dimension.spawnEntity("57d_sbunk:laser_wall", spawn_location);
                    if (entity) {
                        entity.setProperty("property:fs_sbunk_laser_direction", face);
                        if (!FSPlayer.isCreative(player)) {
                            FSInventoryManager.removeItem(player, item, 1);
                        }
                    }
                }
                else {
                    player.playSound("fs.sbunk.chat_ping");
                    player.sendMessage({ translate: FSLocalizedString.localize("chat.laser_beam.invalid_location_0", "§c[!] Invalid location", "Invalid location message") });
                }
            }
        }
        else if (item === "57d_sbunk:laser_floor") {
            const location = player.getHeadLocation();
            const direction = player.getViewDirection();
            const dimension = player.dimension;
            const rco = {
                maxDistance: 6,
                includeLiquidBlocks: true,
                includePassableBlocks: true
            };
            const raycast_hit = dimension.getBlockFromRay(location, direction, rco);
            if (raycast_hit && raycast_hit.block) {
                const block = raycast_hit.block;
                const face = raycast_hit.face;
                if (face !== Direction.Up) {
                    player.playSound("fs.sbunk.chat_ping");
                    player.sendMessage({ translate: FSLocalizedString.localize("chat.laser_beam.place_on_floor", "§c[!] You must place the laser beam on the floor", "Laser not placed on the floor warning message") });
                    return;
                }
                const block_above = block.above(1);
                if (block_above && block_above.permutation.matches("minecraft:air")) {
                    const spawn_location = block_above.bottomCenter();
                    const entity = dimension.spawnEntity("57d_sbunk:laser_floor", spawn_location);
                    if (entity) {
                        entity.setProperty("property:fs_sbunk_laser_direction", face);
                        if (!FSPlayer.isCreative(player)) {
                            FSInventoryManager.removeItem(player, item, 1);
                        }
                    }
                }
                else {
                    player.playSound("fs.sbunk.chat_ping");
                    player.sendMessage({ translate: FSLocalizedString.localize("chat.laser_beam.invalid_location_1", "§c[!] Invalid location", "Invalid location") });
                }
            }
        }
    }
    static outputLaserBeamRequiresLaserConsoleMessage(entity, initiator) {
        const location = entity.location;
        const eqo = {
            location: location,
            maxDistance: LASER_CONSOLE_DISTANCE,
            type: "57d_sbunk:laser_console"
        };
        const nearby_laser_console_found = entity.dimension.getEntities(eqo).length > 0;
        let color_code = "§c";
        let message = FSLocalizedString.localize("laser_console.need_laser_console.message", "You also need a nearby `Laser Console` to control the laser.", "Message to inform the player that they need a Laser Console to control the laser.");
        if (nearby_laser_console_found) {
            color_code = "§b";
            message = FSLocalizedString.localize("laser_console.use_laser_console.message", "Use the nearby `Laser Console` to control the laser.", "Message to inform the player that they need to use the nearby Laser Console to control the laser.");
        }
        if (initiator instanceof Player) {
            initiator.playSound("fs.sbunk.chat_ping");
        }
        else if (initiator instanceof World) {
            initiator.playSound("fs.sbunk.chat_ping", entity.location);
        }
        initiator.sendMessage({
            rawtext: [{ text: `${color_code}[!] ` }, { translate: message }]
        });
    }
}

//# sourceMappingURL=../../../../_SBUNK_BPDebug/fs_sbunk/entity/LaserBeam.js.map
