import { system, BlockPermutation } from "@minecraft/server"


export class ElevatorFloorComponent {
    constructor() {
        this.onPlayerInteract = this.onPlayerInteract.bind(this);

    }

    onPlayerInteract(e) {
        const block = e.block;
        const player = e.player;
        let selectedSlot = player.selectedSlotIndex;
        let handItem = player.getComponent("inventory").container.getItem(selectedSlot);

        if (handItem) {
            if (handItem.typeId == "pb_red:redstone_wrench") {
                // remove elevator floor
                block.dimension.runCommand(`playsound vr.stutterturn @a ${block.location.x} ${block.location.y} ${block.location.z}`)
                block.setPermutation(BlockPermutation.resolve("minecraft:air"))
                return;
            }
        }
    }
}



export class ElevatorRailComponent {
    constructor() {
        this.onTick = this.onTick.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);
        this.tickCpt = 0
    }

    onPlayerInteract(e) {
        const block = e.block;

        const player = e.player;
        let selectedSlot = player.selectedSlotIndex;
        let handItem = player.getComponent("inventory").container.getItem(selectedSlot);

        if (handItem) {
            if (handItem.typeId == "pb_red:redstone_wrench") {
                const AllStates = [
                    { state: "minecraft:cardinal_direction", values: ["north", "east", "south", "west"] },
                    { state: "minecraft:facing_direction", values: ["north", "east", "south", "west", "up", "down"] }
                ]

                AllStates.some((stateObj) => {
                    const currentState = block.permutation.getState(stateObj.state);

                    if (currentState !== undefined && currentState !== null) {
                        const stateValues = stateObj.values;
                        const currentStateIndex = stateValues.indexOf(currentState);
                        const nextState = currentStateIndex >= stateValues.length - 1 ? stateValues[0] : stateValues[currentStateIndex + 1];

                        block.setPermutation(block.permutation.withState(stateObj.state, nextState));
                        block.dimension.runCommand(`playsound vr.stutterturn @a ${block.location.x} ${block.location.y} ${block.location.z}`)
                    }
                });
            }
        }
    }

    onTick(e) {
        const block = e.block;
        const direction = block.permutation.getState('minecraft:cardinal_direction');
        const elevatorBlock = this.getBlockInDirection(block, direction);
        if (!elevatorBlock) return
        const elevatorBlockCenter = { x: elevatorBlock.location.x + 0.5, y: elevatorBlock.location.y + 0.5, z: elevatorBlock.location.z + 0.5 }
        const elevatorEntity = block.dimension.getEntities({
            location: elevatorBlockCenter,
            maxDistance: 1,
            type: 'pb_red:elevator'
        })[0];

        if (!elevatorEntity) return

        const nearbyPlayers = block.dimension.getEntities({
            location: elevatorEntity.location,
            maxDistance: 2,
            type: 'minecraft:player'
        });
        for (const player of nearbyPlayers)
            if (player && elevatorEntity.hasTag("pb_red:hasPlayerRider")) {
                player.runCommand("playanimation @s animation.pb_red.player.custom_ride")
            }
        const isGoingUp = elevatorEntity.hasTag('pb_red:elevator_up');
        const isGoingDown = elevatorEntity.hasTag('pb_red:elevator_down');
        this.tickCpt++

        if (isGoingUp) {
            if (this.tickCpt % 5 == 0) {
                block.dimension.runCommand(`playsound pb_red.elevator_loop @a ${block.location.x} ${block.location.y} ${block.location.z} 0.1`)
            }
            if (block.above().typeId !== "pb_red:elevator_rail" && block.above().typeId !== "pb_red:elevator_control_rail") {
                elevatorEntity.removeTag('pb_red:elevator_up');
                elevatorEntity.addTag('pb_red:elevator_down');
            } else {
                elevatorEntity.teleport({ x: elevatorBlockCenter.x, y: elevatorEntity.location.y + 0.1, z: elevatorBlockCenter.z });
            }
        } else if (isGoingDown) {
            if (this.tickCpt % 38 == 0) {
                block.dimension.runCommand(`playsound pb_red.elevator_loop @a ${block.location.x} ${block.location.y} ${block.location.z} 0.2`)
            }
            if (block.below().typeId !== "pb_red:elevator_rail" && block.below().typeId !== "pb_red:elevator_control_rail") {
                elevatorEntity.removeTag('pb_red:elevator_down');
                elevatorEntity.addTag('pb_red:elevator_up');
            } else {
                elevatorEntity.teleport({ x: elevatorBlockCenter.x, y: elevatorEntity.location.y - 0.1, z: elevatorBlockCenter.z });
            }
        }
    }
    getBlockInDirection(block, direction) {
        switch (direction) {
            case 'north':
                return block.south(2);
            case 'south':
                return block.north(2);
            case 'east':
                return block.west(2);
            case 'west':
                return block.east(2);
        }
    }
}

export class ElevatorControlRailComponent {
    constructor() {
        this.onTick = this.onTick.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);
        this.emptyFloor = {}
        this.REDSTONE_POWER_BLOCKS = [
            { id: "minecraft:redstone_wire", state: "redstone_signal" },
            { id: "minecraft:powered_comparator", state: "minecraft:cardinal_direction" },
            { id: "minecraft:powered_repeater", state: "minecraft:cardinal_direction" },
            { id: "minecraft:redstone_torch", state: "torch_facing_direction" },
            { id: "minecraft:observer", state: "minecraft:facing_direction" },
            { id: "minecraft:lever", state: "open_bit" },
            { id: "minecraft:lever", state: "open_bit" },
            { id: "_button", state: "button_pressed_bit" },
            { id: "_pressure_plate", state: "redstone_signal" },
            { id: "minecraft:redstone_block", state: null },
        ];
    }

    onPlayerInteract(e) {
        const block = e.block;
        const player = e.player;
        const direction = block.permutation.getState('minecraft:cardinal_direction');
        const elevatorBlock = this.getBlockInDirection(block, direction);
        const elevatorBlockCenter = { x: elevatorBlock.location.x + 0.5, y: elevatorBlock.location.y + 0.5, z: elevatorBlock.location.z + 0.5 }

        const selectedSlot = player.selectedSlotIndex;
        const handItem = player.getComponent("inventory").container?.getItem(selectedSlot);
        if (!handItem) return

        if (handItem.typeId == "pb_red:redstone_wrench") {
            const AllStates = [
                { state: "minecraft:cardinal_direction", values: ["north", "east", "south", "west"] },
                { state: "minecraft:facing_direction", values: ["north", "east", "south", "west", "up", "down"] }
            ]

            AllStates.some((stateObj) => {
                const currentState = block.permutation.getState(stateObj.state);

                if (currentState !== undefined && currentState !== null) {
                    const stateValues = stateObj.values;
                    const currentStateIndex = stateValues.indexOf(currentState);
                    const nextState = currentStateIndex >= stateValues.length - 1 ? stateValues[0] : stateValues[currentStateIndex + 1];

                    block.setPermutation(block.permutation.withState(stateObj.state, nextState));
                    block.dimension.runCommand(`playsound vr.stutterturn @a ${block.location.x} ${block.location.y} ${block.location.z}`)
                }
            });
        }

        if (handItem?.typeId == "pb_red:spawn_elevator") {
            // console.warn("intercat good")
            const entity = block.dimension.getEntities({ location: elevatorBlockCenter, maxDistance: 3, type: "pb_red:elevator" })[0]
            if (!entity) {
                const elevatorEntity = block.dimension.spawnEntity("pb_red:elevator", elevatorBlockCenter)
                elevatorEntity.teleport(elevatorBlockCenter, { rotation: { x: 0, y: this.getDirectionRotation(direction) } })
                elevatorEntity.nameTag = "§r"
                player.runCommand('clear @s pb_red:spawn_elevator 0 1')
                block.dimension.runCommand(`playsound mob.agent.spawn @a ${block.location.x} ${block.location.y} ${block.location.z}`)
            } else {
                // console.warn("There's already an elevator here")
            }

        }

        if (handItem?.typeId == "pb_red:spawn_elevator_cabin") {
            // console.warn("intercat good")
            const entity = block.dimension.getEntities({ location: elevatorBlockCenter, maxDistance: 3, type: "pb_red:elevator" })[0]
            if (!entity) {
                const elevatorEntity = block.dimension.spawnEntity("pb_red:elevator", elevatorBlockCenter)
                elevatorEntity.setProperty("pb_red:is_room", true)
                elevatorEntity.teleport(elevatorBlockCenter, { rotation: { x: 0, y: this.getDirectionRotation(direction) } })
                elevatorEntity.nameTag = "§r"
                player.runCommand('clear @s pb_red:spawn_elevator_cabin 0 1')
                block.dimension.runCommand(`playsound mob.agent.spawn @a ${block.location.x} ${block.location.y} ${block.location.z}`)
            } else {
                // console.warn("There's already an elevator here")
            }

        }
    }

    onTick(e) {
        const block = e.block;
        const direction = block.permutation.getState('minecraft:cardinal_direction');
        const leftBlock = this.getSideBlock(block, direction, 'left');
        const rightBlock = this.getSideBlock(block, direction, 'right');
        const elevatorBlock = this.getBlockInDirection(block, direction);
        if (!elevatorBlock) return
        const elevatorBlockCenter = { x: elevatorBlock.location.x + 0.5, y: elevatorBlock.location.y + 0.5, z: elevatorBlock.location.z + 0.5 }

        let newState = 'stop';

        if (this.isPowered(leftBlock.block, leftBlock.dir) && this.isPowered(rightBlock.block, rightBlock.dir)) {
            newState = 'stop';
        } else {
            if (this.isPowered(leftBlock.block, leftBlock.dir)) {
                newState = 'up';
            } else if (this.isPowered(rightBlock.block, rightBlock.dir)) {
                newState = 'down';
            }
        }

        if (block.permutation.getState('pb_red:control_state') !== newState) {
            block.setPermutation(block.permutation.withState('pb_red:control_state', newState));
        }

        const elevatorEntity = block.dimension.getEntities({
            location: elevatorBlockCenter,
            maxDistance: 0.5,
            type: 'pb_red:elevator'
        })[0];


        if (elevatorEntity) {

            if (elevatorEntity.hasTag("pb_red:elevator_is_beeing_destroyed")) return;

            const elevatorId = elevatorEntity.id
            const nearbyPlayers = block.dimension.getEntities({
                location: elevatorEntity.location,
                maxDistance: 2,
                type: 'minecraft:player'
            })[0];
            if (nearbyPlayers && elevatorEntity.hasTag("pb_red:hasPlayerRider")) {
                nearbyPlayers.runCommand("playanimation @s animation.pb_red.player.custom_ride")
            }

            const isGoingUp = elevatorEntity.hasTag('pb_red:elevator_up');
            const isGoingDown = elevatorEntity.hasTag('pb_red:elevator_down');

            if (elevatorEntity.getProperty("pb_red:is_room")) {
                if (!elevatorEntity.hasTag("pb_red:elevator_in_doors_action")) {
                    if ((isGoingDown || isGoingUp) && elevatorEntity.getProperty("pb_red:doors_open") == true) {
                        elevatorEntity.setProperty("pb_red:doors_open", false)

                        elevatorEntity.addTag("pb_red:elevator_in_doors_action")
                        system.runTimeout(() => {
                            try {
                                elevatorEntity.removeTag("pb_red:elevator_in_doors_action")
                            } catch { }
                        }, 20)

                    } else if ((!isGoingDown && !isGoingUp) && elevatorEntity.getProperty("pb_red:doors_open") == false) {
                        elevatorEntity.setProperty("pb_red:doors_open", true)

                        elevatorEntity.addTag("pb_red:elevator_in_doors_action")
                        system.runTimeout(() => {
                            try {
                                elevatorEntity.removeTag("pb_red:elevator_in_doors_action")
                            } catch { }
                        }, 20)

                    }
                }

            }


            if (isGoingUp) {
                elevatorEntity.teleport({ x: elevatorBlockCenter.x, y: elevatorEntity.location.y + 0.1, z: elevatorBlockCenter.z });
            } else if (isGoingDown) {
                elevatorEntity.teleport({ x: elevatorBlockCenter.x, y: elevatorEntity.location.y - 0.1, z: elevatorBlockCenter.z });
            } else {
                elevatorEntity.teleport({ x: elevatorBlockCenter.x, y: elevatorBlockCenter.y, z: elevatorBlockCenter.z });
            }


            // Check if the elevator entity has reached the center of the block
            if (Math.abs(elevatorEntity.location.y - (block.location.y + 0.5)) <= 0.1) {
                elevatorEntity.teleport({ x: elevatorBlockCenter.x, y: elevatorBlockCenter.y, z: elevatorBlockCenter.z });
                const elevatorFloor = `fill ${elevatorBlockCenter.x - 1} ${elevatorBlockCenter.y} ${elevatorBlockCenter.z - 1} ${elevatorBlockCenter.x + 1} ${elevatorBlockCenter.y} ${elevatorBlockCenter.z + 1} pb_red:elevator_floor keep`
                const emptyFloor = `fill ${elevatorBlockCenter.x - 1} ${elevatorBlockCenter.y} ${elevatorBlockCenter.z - 1} ${elevatorBlockCenter.x + 1} ${elevatorBlockCenter.y} ${elevatorBlockCenter.z + 1} minecraft:air replace`

                if (newState === 'up') {
                    if (block.above().typeId == "pb_red:elevator_rail" || block.above().typeId == "pb_red:elevator_control_rail") {
                        elevatorEntity.removeTag('pb_red:elevator_down');
                        elevatorEntity.addTag('pb_red:elevator_up');
                        block.dimension.runCommand(emptyFloor);
                        this.emptyFloor[elevatorId] = true;
                        system.runTimeout(() => {
                            this.emptyFloor[elevatorId] = false
                        }, 11);
                    } else {
                        elevatorEntity.removeTag('pb_red:elevator_up');
                        elevatorEntity.removeTag('pb_red:elevator_down');
                        this.scheduleFloorUpdate(block, elevatorFloor, elevatorId, elevatorEntity);
                    }
                } else if (newState === 'down') {
                    if (block.below().typeId == "pb_red:elevator_rail" || block.below().typeId == "pb_red:elevator_control_rail") {
                        elevatorEntity.removeTag('pb_red:elevator_up');
                        elevatorEntity.addTag('pb_red:elevator_down');
                        block.dimension.runCommand(emptyFloor);
                        this.emptyFloor[elevatorId] = true;
                        system.runTimeout(() => {
                            this.emptyFloor[elevatorId] = false
                        }, 11);
                    } else {
                        elevatorEntity.removeTag('pb_red:elevator_up');
                        elevatorEntity.removeTag('pb_red:elevator_down');
                        this.scheduleFloorUpdate(block, elevatorFloor, elevatorId, elevatorEntity);
                    }
                } else if (newState === 'stop') {
                    elevatorEntity.removeTag('pb_red:elevator_up');
                    elevatorEntity.removeTag('pb_red:elevator_down');
                    this.scheduleFloorUpdate(block, elevatorFloor, elevatorId, elevatorEntity);
                }


            }
        }
    }

    scheduleFloorUpdate(block, elevatorFloor, elevatorId, entity) {
        system.runTimeout(() => {
            try {
                if (entity.hasTag("pb_red:elevator_is_beeing_destroyed") || !entity) return;
            } catch { return }

            if (!this.emptyFloor[elevatorId]) {
                try {
                    block.dimension.runCommand(elevatorFloor);
                } catch { }
            }
        }, 10);
    }

    getBlockInDirection(block, direction) {
        switch (direction) {
            case 'north':
                return block.south(2);
            case 'south':
                return block.north(2);
            case 'east':
                return block.west(2);
            case 'west':
                return block.east(2);
        }
    }
    getDirectionRotation(direction) {
        switch (direction) {
            case 'north':
                return 180;
            case 'south':
                return 0;
            case 'east':
                return 270;
            case 'west':
                return 90;
        }
    }
    getSideBlock(block, direction, side) {
        switch (direction) {
            case 'north':
                return side === 'left' ? { block: block.west(), dir: 'west' } : { block: block.east(), dir: 'east' };
            case 'south':
                return side === 'left' ? { block: block.east(), dir: 'east' } : { block: block.west(), dir: 'west' };
            case 'east':
                return side === 'left' ? { block: block.south(), dir: 'south' } : { block: block.north(), dir: 'north' };
            case 'west':
                return side === 'left' ? { block: block.north(), dir: 'north' } : { block: block.south(), dir: 'south' };
        }
    }

    getOppositeDirection(direction) {
        switch (direction) {
            case 'north':
                return 'south';
            case 'south':
                return 'north';
            case 'east':
                return 'west';
            case 'west':
                return 'east';
            case 'up':
                return 'down';
            case 'down':
                return 'up';
        }
    }

    isPowered(adjacentBlock, direction) {
        if (!adjacentBlock) return false;

        const redstoneBlock = this.REDSTONE_POWER_BLOCKS.find(({ id }) => adjacentBlock.typeId.includes(id));
        if (!redstoneBlock) return false;

        const { id, state } = redstoneBlock;
        if (id === "minecraft:redstone_block") return true;

        if (id === "minecraft:redstone_wire") {
            let redstonePowerState = adjacentBlock.permutation.getState(state);
            return redstonePowerState > 0;
        }

        if (id === "minecraft:powered_comparator" || id === "minecraft:powered_repeater") {
            return adjacentBlock.permutation.getState(state) === direction;
        }

        if (id === "minecraft:redstone_torch") {
            return adjacentBlock.permutation.getState(state) !== this.getOppositeDirection(direction);
        }

        if (id === "minecraft:observer") {
            return adjacentBlock.permutation.getState(state) == direction && adjacentBlock.permutation.getState("powered_bit") == true;
        }

        if (id === "minecraft:lever") {
            return adjacentBlock.permutation.getState(state) == true;
        }

        if (id === "_button") {
            return adjacentBlock.permutation.getState(state) == true;
        }

        if (id === "_pressure_plate") {
            return adjacentBlock.permutation.getState(state) > 0;
        }

        return false;
    }
}

