import { Direction, EasingType, system, world } from "@minecraft/server";
import PlayerHelper from "./PlayerHelper";
import SecurityDoor from "./entity/SecurityDoor";
import StructureManager from "./StructureManager";
import FSDynamicProperty from "./fs/libs/FSDynamicProperty";
import FormManager from "./FormManager";
import EntranceManager from "./EntranceManager";
import FSPlayerPerms from "./fs/libs/perms/FSPlayerPerms";
import FSEntityPerms from "./fs/libs/perms/FSEntityPerms";
import FSWorldHelper from "./fs/FSWorldHelper";
import * as mcui from "@minecraft/server-ui";
import FSLocalizedString from "./fs/FSLocalizedString";
import FSInventoryManager from "./fs/libs/FSInventoryManager";
import FSMath from "./fs/FSMath";
import { CAMERA_COST_XP, ELEVATOR_LOOKUP_END_DISTANCE, ELEVATOR_LOOKUP_RADIUS, ELEVATOR_LOOKUP_START_DISTANCE, META_ASSET_USERNAME, META_ASSET_USERNAME_TO_REPLACE, RAYCAST_MAX_DISTANCE, RUN_META_ASSET_LOGIC, TURRET_COST_XP } from "./fs/FSConstants";
import SecretEntrance from "./entity/SecretEntrance";
import FSUtil from "./fs/FSUtil";
import FSXPHelper from "./fs/FSXPHelper";
import CameraManager from "./CameraManager";
import LaserBeam from "./entity/LaserBeam";
import FSMemoryProperty from "./fs/libs/FSMemoryProperty";
export default class PlayerManager {
    constructor() {
    }
    static sharedInstance() {
        if (!PlayerManager.instance) {
            PlayerManager.instance = new PlayerManager();
        }
        return PlayerManager.instance;
    }
    init() {
        world.afterEvents.playerJoin.subscribe(this.handlePlayerJoin.bind(this));
        world.afterEvents.playerJoin.subscribe(this.handlePlayerJoin.bind(this));
        world.afterEvents.playerSpawn.subscribe(this.handlePlayerSpawn.bind(this));
        world.afterEvents.itemStartUse.subscribe(this.handleItemStartUse.bind(this));
        world.afterEvents.itemStartUseOn.subscribe(this.handleItemStartUseOn.bind(this));
        world.afterEvents.itemUseOn.subscribe(this.handleItemUseOn.bind(this));
        world.beforeEvents.itemUseOn.subscribe(this.handleBeforeItemUseOn.bind(this));
        world.beforeEvents.itemUse.subscribe(this.handleBeforeItemUse.bind(this));
    }
    tickAllPlayers() {
        world.getPlayers().forEach(player => {
            PlayerManager.sharedInstance().tick(player);
            if (RUN_META_ASSET_LOGIC) {
                if (player.nameTag === META_ASSET_USERNAME_TO_REPLACE) {
                    player.nameTag = META_ASSET_USERNAME;
                }
            }
            else {
                if (player.nameTag === META_ASSET_USERNAME) {
                    player.nameTag = META_ASSET_USERNAME_TO_REPLACE;
                }
            }
        });
    }
    tickAllPlayers10() {
        world.getPlayers().forEach(player => {
            let items = ["57d_sbunk:secret_door", "57d_sbunk:secret_trapdoor", "57d_sbunk:secret_wall", "57d_sbunk:secret_floor", "57d_sbunk:secret_stairs"];
            items.forEach(item => {
                if (FSInventoryManager.isHoldingItem(player, item)) {
                    SecretEntrance.raycastTestForSecretEntranceItem(player, item);
                }
                else {
                    SecretEntrance.removeSecretEntranceGuide(player, item);
                }
            });
            if (player.isSneaking) {
                items = ["57d_sbunk:camera"];
                items.forEach(item => {
                    if (FSInventoryManager.isHoldingItem(player, item)) {
                        if (!this.isInCameraPlacementMode(player)) {
                            this.enterCameraPlacementMode(player);
                        }
                    }
                });
            }
            else {
                this.exitCameraPlacementMode(player);
            }
        });
    }
    tickAllPlayers20() {
        world.getPlayers().forEach(player => {
            this.checkForBlueprintWall(player);
        });
    }
    handlePlayerJoin(eventData) { }
    handlePlayerSpawn(eventData) {
        let player = eventData.player;
        let player_id = player.id.replace(/-/g, "");
        let key = `sbunk_book_given_${player_id}`;
        if (!FSDynamicProperty.getBoolean(world, key)) {
            PlayerHelper.giveBook(player);
            FSDynamicProperty.setBoolean(world, key, true);
        }
        if (!FSDynamicProperty.getBoolean(player, "has_been_given_tablet")) {
            const command_give = `/give "${player.name}" fs_sbunk:tablet 1`;
            player.runCommand(command_give);
            FSDynamicProperty.setBoolean(player, "has_been_given_tablet", true);
            FSWorldHelper.replaceTablets();
        }
    }
    enterTurretPlacementMode(player) {
        FSDynamicProperty.setBoolean(player, "is_placing_turret", true);
        FSInventoryManager.replaceItemInHand(player, "fs_sbunk:tablet_defence", 1);
        FSWorldHelper.replaceTablets();
    }
    confirmTurretPlacement(player) {
        if (!FSDynamicProperty.getBoolean(player, "is_placing_turret")) {
            this.exitTurretPlacementMode(player);
            return;
        }
        if (!FSMemoryProperty.getBoolean(player, "valid_turret_placement")) {
            player.playSound("fs.sbunk.chat_ping");
            player.sendMessage({ translate: FSLocalizedString.localize("chat.turret.invalid_location_turret", "§l§cInvalid Location:§r Turrets can only be placed the ground.", "Invalid location for turret placement") });
            player.sendMessage({ translate: FSLocalizedString.localize("chat.turret.invalid_location_turret.tip", "§l§aPlacement Tip:§r Make sure the area is also clear!", "Tip for turret placement") });
            return;
        }
        const form = new mcui.ActionFormData();
        form.title({ translate: FSLocalizedString.localize("ui.turret.confirm_turret_placement", "Confirm Turret Placement", "Title for the confirm turret placement form") });
        form.body({ translate: FSLocalizedString.localize("ui.turretconfirm_turret_placement_body", "Are you sure you would like to place a turret here? §aTIP: After placing a turret, you can interact with it to change its settings.", "Body for the confirm turret placement form") });
        form.button({ translate: FSLocalizedString.localize("ui.turret.place_turret", "Place Turret", "Button to place a turret") });
        form.button({ translate: FSLocalizedString.localize("ui.turret.cancel", "Cancel", "Button to cancel the turret placement") });
        form.show(player).then(resp => {
            if (resp.canceled) {
                return;
            }
            let selection = resp.selection || 0;
            switch (selection) {
                case 0: {
                    try {
                        let last_turret_loc = FSDynamicProperty.getVector3(player, "last_turret_loc");
                        this.exitTurretPlacementMode(player, false, true);
                        player.dimension.runCommand("/summon 57d_sbunk:security_turret " + last_turret_loc.x + " " + last_turret_loc.y + " " + last_turret_loc.z + " 0 0");
                        world.playSound("57d_sbunk.turret_start", last_turret_loc);
                        const msg = {
                            rawtext: [
                                { text: "§g[!] " },
                                {
                                    translate: FSLocalizedString.localize("turret.added", "A new Security Turret has been added!", "Output to chat when a new turret is added by a player.")
                                }
                            ]
                        };
                        FSPlayerPerms.sharedInstance().forceSendMessageToAllAdmins(msg);
                    }
                    catch (error) { }
                    break;
                }
                case 1: {
                    this.exitTurretPlacementMode(player);
                    break;
                }
            }
        });
    }
    exitTurretPlacementMode(player, didCancel = false, didPlace = false) {
        if (FSDynamicProperty.getBoolean(player, "is_placing_turret") && didCancel) {
            player.playSound("57d_sbunk.power_down");
            player.onScreenDisplay.setActionBar({ translate: FSLocalizedString.localize("actionbar.exiting_turret_placement_mode", "Cancelled turret placement!", "Message for exiting turret placement mode") });
        }
        const shouldCharge = player.getDynamicProperty(FSUtil.namespacedString("will_charge_xp_for_placement")) || false;
        if (didPlace) {
            if (shouldCharge) {
                FSXPHelper.removeXP(player, TURRET_COST_XP);
                player.onScreenDisplay.setActionBar({ translate: FSLocalizedString.localize("actionbar.turret_placed_for_xp", "Turret placed for %1 XP", "Message for placing a turret"), with: [`${TURRET_COST_XP}`] });
                player.setDynamicProperty(FSUtil.namespacedString("will_charge_xp_for_placement"), false);
            }
            else {
                player.onScreenDisplay.setActionBar({ translate: FSLocalizedString.localize("actionbar.turret_placed", "Turret placed!", "Message for placing a turret") });
            }
        }
        FSDynamicProperty.setBoolean(player, "is_placing_turret", false);
        try {
            let last_turret_loc = FSDynamicProperty.getVector3(player, "last_turret_loc");
            FSWorldHelper.fillBlocks(player.dimension, last_turret_loc, last_turret_loc, "minecraft:air");
        }
        catch (error) {
        }
        finally {
        }
        FSDynamicProperty.clear(player, "last_turret_loc");
    }
    isInCameraPlacementMode(player) {
        return FSDynamicProperty.getBoolean(player, "is_placing_camera");
    }
    enterCameraPlacementMode(player) {
        FSDynamicProperty.setBoolean(player, "is_placing_camera", true);
    }
    confirmCameraPlacement(player) {
        if (!FSDynamicProperty.getVector3(player, "is_placing_camera")) {
            this.exitCameraPlacementMode(player);
            return;
        }
        if (!FSMemoryProperty.getBoolean(player, "valid_camera_placement")) {
            player.playSound("fs.sbunk.chat_ping");
            player.sendMessage({ translate: FSLocalizedString.localize("chat.camera.invalid_location_camera", "§l§cInvalid Location:§r Cameras can only be placed on walls, ceilings, and floor.", "Invalid location for camera placement") });
            player.sendMessage({ translate: FSLocalizedString.localize("chat.turret.invalid_location_camera.tip", "§l§aPlacement Tip:§r Make sure the area is also clear!", "Tip for camera placement") });
            return;
        }
        FSDynamicProperty.setBoolean(player, "in_camera_dialogue", true);
        const form = new mcui.ActionFormData();
        form.title({ translate: FSLocalizedString.localize("ui.camera.confirm_camera_placement", "Confirm Camera Placement", "Title for the confirm camera placement form") });
        form.body({ translate: FSLocalizedString.localize("ui.camera.confirm_camera_placement_body", "Are you sure you would like to place a camera here? §aTIP: After placing a camera, you can interact with it to change its settings.", "Body for the confirm camera placement form") });
        form.button({ translate: FSLocalizedString.localize("ui.camera.place_camera", "Place Camera", "Button to place a camera") });
        form.button({ translate: FSLocalizedString.localize("ui.camera.cancel", "Cancel", "Button to cancel the camera placement") });
        form.show(player).then(resp => {
            FSDynamicProperty.clear(player, "in_camera_dialogue");
            if (resp.canceled) {
                PlayerManager.sharedInstance().exitCameraPlacementMode(player, true, false);
                return;
            }
            let selection = resp.selection || 0;
            switch (selection) {
                case 0: {
                    try {
                        let last_camera_loc = FSDynamicProperty.getVector3(player, "last_camera_loc");
                        let last_camera_rot = FSDynamicProperty.getNumber(player, "last_camera_rot");
                        let last_camera_placement = FSDynamicProperty.getString(player, "last_camera_placement");
                        if (last_camera_placement.length === 0) {
                            last_camera_placement = "wall";
                        }
                        player.dimension.runCommand(`/summon 57d_sbunk:camera ${last_camera_loc.x} ${last_camera_loc.y} ${last_camera_loc.z} ${last_camera_rot} 0 fs_sbunk:set_placement_${last_camera_placement}`);
                        world.playSound("57d_sbunk.camera_placed", last_camera_loc);
                    }
                    catch (error) { }
                    this.exitCameraPlacementMode(player, false, true);
                    break;
                }
                case 1: {
                    PlayerManager.sharedInstance().exitCameraPlacementMode(player, true, false);
                    break;
                }
            }
        });
    }
    exitCameraPlacementMode(player, didCancel = false, didPlace = false) {
        if (FSDynamicProperty.getBoolean(player, "in_camera_dialogue")) {
            return;
        }
        if (FSDynamicProperty.getBoolean(player, "is_placing_camera") && didCancel) {
            player.playSound("57d_sbunk.power_down");
            player.onScreenDisplay.setActionBar({ translate: FSLocalizedString.localize("actionbar.exiting_camera_placement_mode", "Cancelled camera placement!", "Message for exiting camera placement mode") });
        }
        if (didPlace) {
            const shouldCharge = player.getDynamicProperty(FSUtil.namespacedString("will_charge_xp_for_placement")) || false;
            if (shouldCharge) {
                FSXPHelper.removeXP(player, CAMERA_COST_XP);
                player.onScreenDisplay.setActionBar({ translate: FSLocalizedString.localize("actionbar.camera_placed_for_xp", "Camera placed for %1 XP", "Message for placing a camera"), with: [`${CAMERA_COST_XP}`] });
                player.setDynamicProperty(FSUtil.namespacedString("will_charge_xp_for_placement"), false);
            }
            else {
                player.onScreenDisplay.setActionBar({ translate: FSLocalizedString.localize("actionbar.camera_placed", "Camera placed!", "Message for placing a camera") });
            }
        }
        FSDynamicProperty.setBoolean(player, "is_placing_camera", false);
        try {
            let last_camera_loc = FSDynamicProperty.getVector3(player, "last_camera_loc");
            FSWorldHelper.fillBlocks(player.dimension, last_camera_loc, last_camera_loc, "minecraft:air");
        }
        catch (error) {
        }
        finally {
        }
        FSDynamicProperty.clear(player, "last_camera_loc");
    }
    handleBeforeItemUse(eventData) { }
    handleBeforeItemUseOn(eventData) {
        const player = eventData.source;
        const block = eventData.block;
        const block_loc = block.location;
        if (!FSPlayerPerms.sharedInstance().isAdmin(player)) {
            return;
        }
        if (eventData.itemStack.typeId.indexOf("fs_sbunk:tablet") !== -1 && eventData.block.permutation.matches("minecraft:chest")) {
            FormManager.sharedInstance().showLockedChestOptions(eventData.source, block, block_loc);
            eventData.cancel = true;
        }
        if (eventData.itemStack.typeId.indexOf("fs_sbunk:tablet") !== -1 && eventData.block.permutation.matches("minecraft:trapped_chest")) {
            FormManager.sharedInstance().showLockedChestOptions(eventData.source, block, block_loc);
            eventData.cancel = true;
        }
        if (eventData.itemStack.typeId.indexOf("fs_sbunk:tablet") !== -1 && eventData.block.permutation.matches("minecraft:ender_chest")) {
            FormManager.sharedInstance().showLockedChestOptions(eventData.source, block, block_loc);
            eventData.cancel = true;
        }
    }
    handleItemUseOn(eventData) { }
    handleItemStartUseOn(eventData) { }
    handleItemStartUse(eventData) {
        const player = eventData.source;
        const itemTypeId = eventData.itemStack.typeId;
        if (itemTypeId === "fs_sbunk:tablet") {
            FSInventoryManager.replaceItemInHand(player, "fs_sbunk:tablet", 1);
            FSWorldHelper.replaceTablets();
            FSPlayerPerms.sharedInstance().revalidateRootUser(player); 
            if (FSDynamicProperty.getBoolean(player, "is_placing_camera")) {
                this.confirmCameraPlacement(player);
            }
            else if (FSDynamicProperty.getBoolean(player, "is_placing_turret")) {
                this.confirmTurretPlacement(player);
            }
            else if (StructureManager.sharedInstance().shouldShowRoomOptions(player)) {
                StructureManager.sharedInstance().showRoomOptions(player);
            }
            else if (StructureManager.sharedInstance().shouldShowCorridorOptions(player)) {
                StructureManager.sharedInstance().showCorridorOptions(player);
            }
            else if (StructureManager.sharedInstance().shouldShowHubCorridorOptions(player)) {
                StructureManager.sharedInstance().showHubCorridorOptions(player);
            }
            else {
                FormManager.sharedInstance().showRootOptions(player);
            }
            return;
        }
        if (itemTypeId === "fs_sbunk:tablet_camera") {
            CameraManager.sharedInstance().showCameraDialogue(player);
            return;
        }
        if (itemTypeId === "57d_sbunk:secret_door" || itemTypeId === "57d_sbunk:secret_trapdoor" || itemTypeId === "57d_sbunk:secret_wall" || itemTypeId === "57d_sbunk:secret_floor" || itemTypeId === "57d_sbunk:secret_stairs") {
            SecretEntrance.playerInteractWithSecretEntranceItem(player, itemTypeId);
            return;
        }
        if (itemTypeId === "57d_sbunk:laser_wall" || itemTypeId === "57d_sbunk:laser_floor") {
            LaserBeam.onItemUsed(player, itemTypeId);
        }
        if (itemTypeId === "57d_sbunk:camera") {
            CameraManager.onItemUsed(player, itemTypeId);
        }
        if (itemTypeId === "57d_sbunk:security_chip") {
            FormManager.sharedInstance().showSecurityChipAbout(player);
        }
    }
    isBlockEntranceFloor(block) {
        if (!block) {
            return false;
        }
        return block.permutation.matches("57d_sbunk:entrance_floor");
    }
    isBlockElevatorFloor(block) {
        if (!block) {
            return false;
        }
        return block.permutation.matches("57d_sbunk:elevator_floor") || block.permutation.matches("57d_sbunk:hub_marker");
    }
    tick(player) {
        let eqo = {
            type: "57d_sbunk:vehicle_hoverboard",
            location: player.location,
            maxDistance: 1,
            closest: 1,
            tags: ["has_rider"]
        };
        let hoverboards = player.dimension.getEntities(eqo);
        if (hoverboards.length > 0) {
            player.runCommand("/playanimation @s animation.player_57d_sbunk_riding_hoverboard");
        }
        let eqo_doors = {
            type: "57d_sbunk:security_door",
            tags: ["fs_sbunk:auto_open"],
            location: player.location,
            maxDistance: 4,
            closest: 1
        };
        let doors = player.dimension.getEntities(eqo_doors);
        if (doors.length > 0) {
            doors.forEach(door => {
                if (!FSDynamicProperty.getBoolean(door, "is_open")) {
                    if (FSEntityPerms.hasPlayerGotPermissionForEntity(player, door, false)) {
                        SecurityDoor.onInteract(door);
                    }
                }
            });
        }
        if (FSDynamicProperty.getBoolean(player, "is_placing_camera")) {
            this.placeCamera(player);
        }
        if (FSDynamicProperty.getBoolean(player, "is_placing_turret")) {
            this.placeTurret(player);
        }
        if (player.isJumping && FSDynamicProperty.getNumber(player, "jump_count") === 0) {
            FSDynamicProperty.setNumber(player, "jump_count", 1);
            if (!this.handleElevatorPlaceableJumping(player)) {
                this.handleElevatorJumping(player);
            }
            if (FSDynamicProperty.getBoolean(player, "is_camera")) {
                PlayerHelper.becomeNextCamera(player);
            }
        }
        if (player.isOnGround) {
            FSDynamicProperty.setNumber(player, "jump_count", 0);
        }
        if (!player.isSneaking) {
            FSDynamicProperty.setBoolean(player, "sneaking_latched", false);
        }
        if (player.isSneaking && !FSDynamicProperty.getBoolean(player, "sneaking_latched")) {
            if (!this.handleElevatorPlaceableSneaking(player)) {
                this.handleElevatorSneaking(player);
            }
            FSDynamicProperty.setBoolean(player, "sneaking_latched", true);
        }
        if (player.isSneaking) {
            this.resetCamera(player);
            this.exitTurretPlacementMode(player, true);
        }
        else {
            this.updateCameraRotation(player);
        }
        let block = PlayerHelper.getBlockUnderPlayer(player);
        if (block?.permutation.matches("57d_sbunk:entrance_floor")) {
            const rawText = {
                rawtext: [{ translate: FSLocalizedString.localize("actionbar.bunker_entry.text", "§lSneak§r to enter the bunker", "Hint for entering the bunker") }]
            };
            player.onScreenDisplay.setActionBar(rawText);
        }
        if (block?.permutation.matches("57d_sbunk:elevator_floor") || block?.permutation.matches("57d_sbunk:hub_marker")) {
            const rawText = {
                rawtext: [{ translate: FSLocalizedString.localize("actionbar.elevator_hint.line_1", "§lSneak§r to go down a level", "Hint for using the elevator") }, { text: "\n" }, { translate: FSLocalizedString.localize("actionbar.elevator_hint.line_2", "§lJump§r to go up a level", "Hint for using the elevator") }]
            };
            player.onScreenDisplay.setActionBar(rawText);
        }
        if (this.isPlayerInElevatorPlaceable(player)) {
            const rawText = {
                rawtext: [
                    { translate: FSLocalizedString.localize("actionbar.elevator_placeable_hint.line_1", "§lSneak§r to go down a level", "Hint for using the elevator") },
                    { text: "\n" },
                    { translate: FSLocalizedString.localize("actionbar.elevator_placeable_hint.line_2", "§lJump§r to go up a level", "Hint for using the elevator") }
                ]
            };
            player.onScreenDisplay.setActionBar(rawText);
        }
    }
    isPlayerInElevatorPlaceable(player) {
        const eqo = {
            type: "57d_sbunk:elevator_placeable",
            location: player.location,
            maxDistance: 1.5,
            closest: 1
        };
        let elevators = player.dimension.getEntities(eqo);
        return elevators.length > 0;
    }
    handleElevatorPlaceableSneaking(player) {
        let elevator_found = false;
        let elevator_below_found = false;
        const eqo = {
            type: "57d_sbunk:elevator_placeable",
            location: player.location,
            maxDistance: 1.5,
            closest: 1
        };
        let elevators = player.dimension.getEntities(eqo);
        if (elevators.length > 0) {
            elevator_found = true;
            const elevator = elevators[0];
            for (let y = ELEVATOR_LOOKUP_START_DISTANCE; y < ELEVATOR_LOOKUP_END_DISTANCE; y++) {
                if (y < elevator.dimension.heightRange.min) {
                    break;
                }
                const eqo = {
                    type: "57d_sbunk:elevator_placeable",
                    location: FSMath.add(elevator.location, { x: 0, y: -y, z: 0 }),
                    maxDistance: ELEVATOR_LOOKUP_RADIUS,
                    closest: 1
                };
                let elevators_below = elevator.dimension.getEntities(eqo);
                if (elevators_below.length > 0) {
                    elevator_below_found = true;
                    const elevator_below = elevators_below[0];
                    player.playSound("fs.sbunk.elevator_move");
                    player.teleport(elevator_below.location);
                    system.runTimeout(() => {
                        this.openNearbyElevatorPlaceable(player);
                    }, 40);
                    break;
                }
            }
        }
        if (elevator_found && !elevator_below_found) {
            const rawText = {
                rawtext: [
                    { translate: FSLocalizedString.localize("actionbar.elevator_placeable_hint.not_found_below.line_1", "§c[!]§r Elevator below not found!", "Warning to the player that another elevator has not been found.") },
                    { text: "\n" },
                    { translate: FSLocalizedString.localize("actionbar.elevator_placeable_hint.not_found_below.line_2", "Place an elevator below this one to travel down.", "Hint to the player about placing elevators.") }
                ]
            };
            player.playSound("fs.sbunk.chat_ping");
            player.sendMessage(rawText);
        }
        return elevator_found;
    }
    handleElevatorPlaceableJumping(player) {
        let elevator_found = false;
        let elevator_above_found = false;
        const eqo = {
            type: "57d_sbunk:elevator_placeable",
            location: player.location,
            maxDistance: 1.5,
            closest: 1
        };
        let elevators = player.dimension.getEntities(eqo);
        if (elevators.length > 0) {
            elevator_found = true;
            const elevator = elevators[0];
            for (let y = ELEVATOR_LOOKUP_START_DISTANCE; y < ELEVATOR_LOOKUP_END_DISTANCE; y++) {
                if (y > elevator.dimension.heightRange.max) {
                    break;
                }
                const eqo = {
                    type: "57d_sbunk:elevator_placeable",
                    location: FSMath.add(elevator.location, { x: 0, y: y, z: 0 }),
                    maxDistance: ELEVATOR_LOOKUP_RADIUS,
                    closest: 1
                };
                let elevators_above = player.dimension.getEntities(eqo);
                if (elevators_above.length > 0) {
                    elevator_above_found = true;
                    const elevator_above = elevators_above[0];
                    player.playSound("fs.sbunk.elevator_move");
                    player.teleport(elevator_above.location);
                    system.runTimeout(() => {
                        this.openNearbyElevatorPlaceable(player);
                    }, 40);
                    break;
                }
            }
        }
        if (elevator_found && !elevator_above_found) {
            const rawText = {
                rawtext: [
                    { translate: FSLocalizedString.localize("actionbar.elevator_placeable_hint.not_found_above.line_1", "§c[!]§r Elevator above not found!", "Warning to the player that another elevator has not been found.") },
                    { text: "\n" },
                    { translate: FSLocalizedString.localize("actionbar.elevator_placeable_hint.not_found_above.line_2", "Place an elevator above this one to travel up.", "Hint to the player about placing elevators.") }
                ]
            };
            player.playSound("fs.sbunk.chat_ping");
            player.sendMessage(rawText);
        }
        return elevator_found;
    }
    handleElevatorSneaking(player) {
        let block = PlayerHelper.getBlockUnderPlayer(player);
        if (this.isBlockEntranceFloor(block)) {
            if (!FSPlayerPerms.sharedInstance().canUseElevator(player)) {
                PlayerHelper.outputElevatorAccessRequired(player);
                return;
            }
            block = PlayerHelper.getBlockOffsetFromPlayer(player, 0, -16, 0);
            if (this.isBlockElevatorFloor(block)) {
                player.playSound("fs.sbunk.elevator_move");
                PlayerHelper.setOffsetLocation(player, 0, -14, 0);
                system.runTimeout(() => {
                    this.openNearbyElevator(player);
                }, 40);
            }
        }
        else if (this.isBlockElevatorFloor(block)) {
            if (!FSPlayerPerms.sharedInstance().canUseElevator(player)) {
                PlayerHelper.outputElevatorAccessRequired(player);
                return;
            }
            block = PlayerHelper.getBlockOffsetFromPlayer(player, 0, -17, 0);
            if (this.isBlockElevatorFloor(block)) {
                player.playSound("fs.sbunk.elevator_move");
                PlayerHelper.setOffsetLocation(player, 0, -15, 0);
                system.runTimeout(() => {
                    this.openNearbyElevator(player);
                }, 40);
            }
            else {
                FormManager.sharedInstance().displayAddLowerLevelDialogue(player);
            }
        }
    }
    handleElevatorJumping(player) {
        let block = PlayerHelper.getBlockUnderPlayer(player);
        if (this.isBlockElevatorFloor(block)) {
            if (!FSPlayerPerms.sharedInstance().canUseElevator(player)) {
                PlayerHelper.outputElevatorAccessRequired(player);
                return;
            }
            block = PlayerHelper.getBlockOffsetFromPlayer(player, 0, 14, 0);
            if (this.isBlockEntranceFloor(block)) {
                player.playSound("note.cow_bell");
                player.playSound("fs.sbunk.elevator_move");
                PlayerHelper.setOffsetLocation(player, 0, 15, 0);
                system.runTimeout(() => {
                    this.openNearbyElevator(player);
                }, 40);
            }
            else {
                block = PlayerHelper.getBlockOffsetFromPlayer(player, 0, 15, 0);
                if (this.isBlockElevatorFloor(block)) {
                    player.playSound("fs.sbunk.elevator_move");
                    PlayerHelper.setOffsetLocation(player, 0, 16, 0);
                    system.runTimeout(() => {
                        this.openNearbyElevator(player);
                    }, 40);
                }
            }
        }
    }
    openNearbyElevator(player) {
        const eqo = {
            type: "57d_sbunk:elevator",
            location: player.location,
            radius: 4,
            closest: 1
        };
        player.dimension.getEntities(eqo).forEach(elevator => {
            EntranceManager.sharedInstance().elevatorOpened(elevator);
        });
    }
    openNearbyElevatorPlaceable(player) {
        const eqo = {
            type: "57d_sbunk:elevator_placeable",
            location: player.location,
            radius: 4,
            closest: 1
        };
        player.dimension.getEntities(eqo).forEach(elevator => {
            EntranceManager.sharedInstance().elevatorOpened(elevator);
        });
    }
    resetCamera(player) {
        player.camera.clear();
        if (FSDynamicProperty.getBoolean(player, "is_camera")) {
            FSDynamicProperty.setBoolean(player, "is_camera", false);
            player.onScreenDisplay.setActionBar({ translate: FSLocalizedString.localize("actionbar.exiting_camera_mode", "Exiting camera mode...", "Message for exiting camera mode") });
        }
    }
    updateCameraRotation(player) {
        const playerProperties = new FSDynamicProperty(player);
        if (playerProperties.getBoolean("is_camera")) {
            const cameraName = playerProperties.getString("camera_name");
            const cameraNameFormatted = cameraName.replace(/\n/g, " ");
            const cameraLocation = playerProperties.getVector3("camera_loc");
            const cameraPlacement = playerProperties.getString("camera_placement");
            var rawText = {
                rawtext: [
                    { text: `${cameraNameFormatted} ` },
                    { text: "\n" },
                    { translate: FSLocalizedString.localize("actionbar.jump_to_view_next_camera", "§bJump to view next camera with matching access level.", "Message for sneaking to exit camera mode") },
                    { text: "\n" },
                    { translate: FSLocalizedString.localize("actionbar.sneak_to_exit_camera_mode", "§cSneak to exit camera mode", "Message for sneaking to exit camera mode") }
                ]
            };
            player.onScreenDisplay.setActionBar(rawText);
            if (cameraPlacement === "wall" || cameraPlacement === "") {
                if (playerProperties.getNumber("camera_dir") === 0) {
                    playerProperties.incrementNumber("camera_rot", 1);
                    if (playerProperties.getNumber("camera_rot") > 45) {
                        playerProperties.setNumber("camera_dir", 1);
                    }
                }
                else if (playerProperties.getNumber("camera_dir") === 1) {
                    playerProperties.incrementNumber("camera_rot", -1);
                    if (playerProperties.getNumber("camera_rot") < -45) {
                        playerProperties.setNumber("camera_dir", 0);
                    }
                }
            }
            else {
                playerProperties.incrementNumber("camera_rot", 1);
            }
            let cameraRotationX = 20;
            if (cameraPlacement === "floor") {
                cameraRotationX = -10;
            }
            const cameraRotation = { x: cameraRotationX, y: playerProperties.getNumber("camera_rot_y") + playerProperties.getNumber("camera_rot") };
            player.camera.setCamera("minecraft:free", { location: cameraLocation, rotation: cameraRotation, easeOptions: { easeTime: 0.25, easeType: EasingType.Linear } });
        }
    }
    placeCamera(player) {
        if (FSDynamicProperty.getBoolean(player, "in_camera_dialogue")) {
            return;
        }
        try {
            if (FSDynamicProperty.getVector3(player, "last_camera_loc")) {
                let last_camera_loc = FSDynamicProperty.getVector3(player, "last_camera_loc");
                FSWorldHelper.fillBlocks(player.dimension, last_camera_loc, last_camera_loc, "minecraft:air");
            }
        }
        catch (error) { }
        const rawText = {
            rawtext: [
                { translate: FSLocalizedString.localize("actionbar.placing_camera", "§lPlacing Camera§r", "Message for placing a camera") },
                { text: "\n" },
                { translate: FSLocalizedString.localize("actionbar.sneak_to_exit_camera_placement_mode", "§bStand to exit camera placement mode", "Message for sneaking to exit camera placement mode") }
            ]
        };
        player.onScreenDisplay.setActionBar(rawText);
        let options = {
            includeLiquidBlocks: false,
            includePassableBlocks: false,
            maxDistance: 32
        };
        let raycastHit = world.getDimension(player.dimension.id).getBlockFromRay(player.getHeadLocation(), player.getViewDirection(), options);
        if (raycastHit && raycastHit.block && !raycastHit.block.permutation.matches("57d_sbunk:camera_placement")) {
            let loc = { x: raycastHit.block.location.x, y: raycastHit.block.location.y, z: raycastHit.block.location.z };
            let test_loc = { x: raycastHit.block.location.x, y: raycastHit.block.location.y, z: raycastHit.block.location.z };
            let valid_placement = true;
            switch (raycastHit.face) {
                case Direction.Up: {
                    loc = { x: raycastHit.block.location.x, y: raycastHit.block.location.y + 1, z: raycastHit.block.location.z };
                    test_loc = { x: raycastHit.block.bottomCenter().x, y: raycastHit.block.bottomCenter().y + 1, z: raycastHit.block.bottomCenter().z };
                    FSDynamicProperty.setNumber(player, "last_camera_rot", PlayerHelper.getSnappedRotation(player, true));
                    FSDynamicProperty.setString(player, "last_camera_placement", "floor");
                    valid_placement = true;
                    break;
                }
                case Direction.Down: {
                    loc = { x: raycastHit.block.location.x, y: raycastHit.block.location.y - 1, z: raycastHit.block.location.z };
                    test_loc = { x: raycastHit.block.bottomCenter().x, y: raycastHit.block.bottomCenter().y - 1, z: raycastHit.block.bottomCenter().z };
                    FSDynamicProperty.setNumber(player, "last_camera_rot", PlayerHelper.getSnappedRotation(player, true));
                    FSDynamicProperty.setString(player, "last_camera_placement", "ceiling");
                    valid_placement = true;
                    break;
                }
                case Direction.South: {
                    loc = { x: raycastHit.block.location.x, y: raycastHit.block.location.y, z: raycastHit.block.location.z + 1 };
                    test_loc = { x: raycastHit.block.bottomCenter().x, y: raycastHit.block.bottomCenter().y, z: raycastHit.block.bottomCenter().z + 1 };
                    FSDynamicProperty.setNumber(player, "last_camera_rot", 0);
                    FSDynamicProperty.setString(player, "last_camera_placement", "wall");
                    break;
                }
                case Direction.West: {
                    loc = { x: raycastHit.block.location.x - 1, y: raycastHit.block.location.y, z: raycastHit.block.location.z };
                    test_loc = { x: raycastHit.block.bottomCenter().x - 1, y: raycastHit.block.bottomCenter().y, z: raycastHit.block.bottomCenter().z };
                    FSDynamicProperty.setNumber(player, "last_camera_rot", 90);
                    FSDynamicProperty.setString(player, "last_camera_placement", "wall");
                    break;
                }
                case Direction.North: {
                    loc = { x: raycastHit.block.location.x, y: raycastHit.block.location.y, z: raycastHit.block.location.z - 1 };
                    test_loc = { x: raycastHit.block.bottomCenter().x, y: raycastHit.block.bottomCenter().y, z: raycastHit.block.bottomCenter().z - 1 };
                    FSDynamicProperty.setNumber(player, "last_camera_rot", 180);
                    FSDynamicProperty.setString(player, "last_camera_placement", "wall");
                    break;
                }
                case Direction.East: {
                    loc = { x: raycastHit.block.location.x + 1, y: raycastHit.block.location.y, z: raycastHit.block.location.z };
                    test_loc = { x: raycastHit.block.bottomCenter().x + 1, y: raycastHit.block.bottomCenter().y, z: raycastHit.block.bottomCenter().z };
                    FSDynamicProperty.setNumber(player, "last_camera_rot", 270);
                    FSDynamicProperty.setString(player, "last_camera_placement", "wall");
                    break;
                }
            }
            let eqo = {
                location: test_loc,
                maxDistance: 0.25,
                closest: 1
            };
            let entities = player.dimension.getEntities(eqo);
            if (entities.length > 0) {
                valid_placement = false;
            }
            FSMemoryProperty.setBoolean(player, "valid_camera_placement", valid_placement);
            try {
                if (valid_placement) {
                    let current_block = world.getDimension(player.dimension.id).getBlock(loc);
                    if (current_block && (current_block.permutation.matches("minecraft:air") || current_block.permutation.matches("minecraft:light_block"))) {
                        FSDynamicProperty.setVector3(player, "last_camera_loc", loc);
                        FSWorldHelper.fillBlocks(player.dimension, loc, loc, "57d_sbunk:camera_placement");
                    }
                }
                else {
                    FSDynamicProperty.clear(player, "last_camera_loc");
                }
            }
            catch (error) { }
        }
    }
    placeTurret(player) {
        try {
            if (FSDynamicProperty.getVector3(player, "last_turret_loc")) {
                let last_camera_loc = FSDynamicProperty.getVector3(player, "last_turret_loc");
                FSWorldHelper.fillBlocks(player.dimension, last_camera_loc, last_camera_loc, "minecraft:air");
            }
        }
        catch (error) { }
        const rawText = {
            rawtext: [
                { translate: FSLocalizedString.localize("actionbar.placing_turret.line_1", "§lPlacing Turret§r", "Message for placing a turret") },
                { text: "\n" },
                { translate: FSLocalizedString.localize("actionbar.placing_turret.line_2", "§bSneak to exit turret placement mode", "Message for sneaking to exit turret placement mode") }
            ]
        };
        player.onScreenDisplay.setActionBar(rawText);
        let options = {
            includeLiquidBlocks: false,
            includePassableBlocks: false,
            maxDistance: 32
        };
        let raycastHit = world.getDimension(player.dimension.id).getBlockFromRay(player.getHeadLocation(), player.getViewDirection(), options);
        if (raycastHit && raycastHit.block && !raycastHit.block.permutation.matches("57d_sbunk:turret_placement")) {
            let loc = { x: raycastHit.block.location.x, y: raycastHit.block.location.y, z: raycastHit.block.location.z };
            let valid_placement = true;
            switch (raycastHit.face) {
                case Direction.Up: {
                    loc = { x: raycastHit.block.location.x, y: raycastHit.block.location.y + 1, z: raycastHit.block.location.z };
                    valid_placement = true;
                    break;
                }
                case Direction.Down: {
                    FSDynamicProperty.clear(player, "last_turret_loc");
                    valid_placement = false;
                    break;
                }
                case Direction.South: {
                    FSDynamicProperty.clear(player, "last_turret_loc");
                    valid_placement = false;
                    break;
                }
                case Direction.West: {
                    FSDynamicProperty.clear(player, "last_turret_loc");
                    valid_placement = false;
                    break;
                }
                case Direction.North: {
                    FSDynamicProperty.clear(player, "last_turret_loc");
                    valid_placement = false;
                    break;
                }
                case Direction.East: {
                    FSDynamicProperty.clear(player, "last_turret_loc");
                    valid_placement = false;
                    break;
                }
            }
            const entityLoc = FSMath.add(raycastHit.block.bottomCenter(), { x: 0, y: 1, z: 0 });
            let eqo = {
                location: entityLoc,
                maxDistance: 0.25,
                closest: 1
            };
            let entities = player.dimension.getEntities(eqo);
            if (entities.length > 0) {
                valid_placement = false;
            }
            FSMemoryProperty.setBoolean(player, "valid_turret_placement", valid_placement);
            try {
                if (valid_placement) {
                    let current_block = world.getDimension(player.dimension.id).getBlock(loc);
                    if (current_block && (current_block.permutation.matches("minecraft:air") || current_block.permutation.matches("minecraft:light_block"))) {
                        FSDynamicProperty.setVector3(player, "last_turret_loc", loc);
                        FSWorldHelper.fillBlocks(player.dimension, loc, loc, "57d_sbunk:turret_placement");
                    }
                }
                else {
                    FSDynamicProperty.clear(player, "last_turret_loc");
                }
            }
            catch (error) { }
        }
    }
    shouldCheckForBlueprintWall(player) {
        if (!FSPlayerPerms.sharedInstance().isAdmin(player)) {
            return false;
        }
        return !FSDynamicProperty.getBoolean(player, "has_built_corridor_0") || !FSDynamicProperty.getBoolean(player, "has_built_corridor_1") || !FSDynamicProperty.getBoolean(player, "has_built_room");
    }
    checkForBlueprintWall(player) {
        if (this.shouldCheckForBlueprintWall(player)) {
            try {
                let options = {
                    includeLiquidBlocks: false,
                    includePassableBlocks: false,
                    maxDistance: RAYCAST_MAX_DISTANCE
                };
                let raycastHit = player.dimension.getBlockFromRay(player.getHeadLocation(), player.getViewDirection(), options);
                let isNearbyBlueprintWall = false;
                if (raycastHit && raycastHit.block) {
                    let blockPermutation = raycastHit.block.permutation;
                    if ((!FSDynamicProperty.getBoolean(player, "has_built_corridor_0") && blockPermutation.matches("57d_sbunk:blockage_hub_corridor")) || blockPermutation.matches("57d_sbunk:marker_hub_corridor")) {
                        const rawText = {
                            rawtext: [
                                { translate: FSLocalizedString.localize("actionbar.tip.expand_here.line_1", "§l§aYou can expand here!§r", "Message for expanding the bunker") },
                                { text: "\n" },
                                { translate: FSLocalizedString.localize("actionbar.tip.expand_here.line_2", "§fInteract with the blueprint wall with your tablet.§r", "Message for interacting with the blueprint wall") }
                            ]
                        };
                        player.onScreenDisplay.setActionBar(rawText);
                        isNearbyBlueprintWall = true;
                    }
                    else if ((!FSDynamicProperty.getBoolean(player, "has_built_corridor_1") && blockPermutation.matches("57d_sbunk:blockage_corridor")) || blockPermutation.matches("57d_sbunk:marker_corridor")) {
                        const rawText = {
                            rawtext: [
                                { translate: FSLocalizedString.localize("actionbar.tip.expand_infinitely.line_1", "§l§aYou can expand §oinfinitely!§r", "Message for expanding the bunker") },
                                { text: "\n" },
                                { translate: FSLocalizedString.localize("actionbar.tip.expand_infinitely.line_2", "§fInteract with the blueprint wall with your tablet.§r", "Message for interacting with the blueprint wall") }
                            ]
                        };
                        player.onScreenDisplay.setActionBar(rawText);
                        isNearbyBlueprintWall = true;
                    }
                    else if ((!FSDynamicProperty.getBoolean(player, "has_built_room") && blockPermutation.matches("57d_sbunk:blockage_room")) || blockPermutation.matches("57d_sbunk:marker_room")) {
                        const rawText = {
                            rawtext: [
                                { translate: FSLocalizedString.localize("actionbar.tip.add_room_here.line_1", "§l§aYou can add a room here!§r", "Message for adding a room") },
                                { text: "\n" },
                                { translate: FSLocalizedString.localize("actionbar.tip.add_room_here.line_2", "§fInteract with the blueprint wall with your tablet.§r", "Message for interacting with the blueprint wall") }
                            ]
                        };
                        player.onScreenDisplay.setActionBar(rawText);
                    }
                    else if (!FSDynamicProperty.getBoolean(player, "has_locked_chest") && blockPermutation.matches("minecraft:chest")) {
                        const rawText = {
                            rawtext: [
                                { translate: FSLocalizedString.localize("actionbar.tip.lockable_chest.line_1", "§l§aYou can lock chests!§r", "Message for adding a room") },
                                { text: "\n" },
                                { translate: FSLocalizedString.localize("actionbar.tip.lockable_chest.line_2", "§fInteract with a chest with your tablet.§r", "Message for interacting with the blueprint wall") }
                            ]
                        };
                        player.onScreenDisplay.setActionBar(rawText);
                    }
                    else if (!FSDynamicProperty.getBoolean(player, "has_locked_door") && blockPermutation.matches("minecraft:iron_door")) {
                        const rawText = {
                            rawtext: [
                                { translate: FSLocalizedString.localize("actionbar.tip.lockable_door.line_1", "§l§aYou can lock chests!§r", "Message for adding a room") },
                                { text: "\n" },
                                { translate: FSLocalizedString.localize("actionbar.tip.lockable_door.line_2", "§fInteract with a chest with your tablet.§r", "Message for interacting with the blueprint wall") }
                            ]
                        };
                        player.onScreenDisplay.setActionBar(rawText);
                    }
                    if (isNearbyBlueprintWall) {
                        const hasReceivedBonusChips = FSDynamicProperty.getBoolean(player, "hasReceivedBonusChips");
                        if (!hasReceivedBonusChips) {
                            const ROOM_COST_AVG = 2;
                            const CORRIDOR_COST_AVG = 2;
                            const bonusChips = ROOM_COST_AVG + CORRIDOR_COST_AVG;
                            FSInventoryManager.addItem(player, "57d_sbunk:security_chip", bonusChips);
                            FSDynamicProperty.setBoolean(player, "hasReceivedBonusChips", true);
                            player.sendMessage({
                                translate: FSLocalizedString.localize("chat.bunker.bonus_chips", "§a[!] You have received %1 Security Chips as a bonus for building your first bunker!", "Bonus chips message"),
                                with: [bonusChips.toString()]
                            });
                            player.playSound("57d_sbunk.cash_register");
                        }
                    }
                }
            }
            catch (error) { }
        }
    }
}

//# sourceMappingURL=../../../_SBUNK_BPDebug/fs_sbunk/PlayerManager.js.map
