import { BlockPermutation, Direction, Player, system, world } from "@minecraft/server";
import { breakBlock, giveItemToPlayer, moveBlock } from "../util/miscUtils";
import { McBlocks } from "../reg/mcBlocks";
import { SuppItems } from "../reg/suppItems";
import { getADirection, isAxisVertical, isFacingSameWay, offsetPos } from "../util/dirUtils";
import { breakWhenPushed, isUnPushable } from "../util/blockProperties";
import { vecAdd } from "../util/mthUtils";
import { configs } from "../configs";
export const RopeWindUpComponent = {
    onPlayerInteract(event) {
        let block = event.block;
        const player = event.player;
        if (!player)
            return;
        if (event.player.isSneaking && configs.ropeInteraction.getValue()) {
            //retract
            if (windRope(block, Direction.Down, -1, BlockPermutation.resolve(McBlocks.Air), "razz_sup:rope" /* SuppBlocks.Rope */)) {
                block.dimension.playSound("razz_sup.rope.break", block.center());
                giveItemToPlayer(player, event.block.getItemStack(1));
            }
        }
        //yeah here we will need to manualy place...
    }
};
export const RopeWalkComponent = {
    onStepOn(event) {
        isOnRope.add(event.entity.id);
    },
    onStepOff(event) {
        const entity = event.entity;
        if (!isFeetBlockRope(entity)) {
            isOnRope.delete(entity.id);
        }
    }
};
world.afterEvents.playerInteractWithBlock.subscribe((event) => {
    if (!event.isFirstEvent)
        return;
    const block = event.block;
    const item = event.itemStack;
    const player = event.player;
    if (block.typeId == "razz_sup:rope" /* SuppBlocks.Rope */ && item.typeId == SuppItems.Rope && !player.isSneaking && configs.ropeInteraction.getValue()) {
        if (isAxisVertical(getADirection(block))) {
            //wind down
            const ropeDown = BlockPermutation.resolve("razz_sup:rope" /* SuppBlocks.Rope */);
            windRope(block, Direction.Down, 1, ropeDown, McBlocks.Air);
        }
    }
});
export const RopeWindDownComponent = {
    onMineBlock(event) {
    }
};
//this code is ass
export function windRope(myBlock, searchDirection, moveDirection, addBehind, canReplaceInFront) {
    const level = myBlock.dimension;
    let lastValidRope = myBlock;
    let depth = 1;
    const canPassThrough = "razz_sup:pulley" /* SuppBlocks.PulleyBlock */;
    while (true) {
        const b = offsetPos(myBlock, searchDirection, depth);
        //what to do when block isnt valid??
        if (!b || !b.isValid()) {
            return false;
        }
        if (b.typeId == canPassThrough && isFacingSameWay(b, myBlock)) {
            depth++;
        }
        else if (b.typeId == myBlock.typeId && isFacingSameWay(b, myBlock)) {
            depth++;
            lastValidRope = b;
        }
        else {
            break;
        }
    }
    let blockIWantToMove = offsetPos(lastValidRope, searchDirection);
    if (!blockIWantToMove || !blockIWantToMove.isValid()) {
        return false;
    } //unloaded chunks
    if (!canMove(blockIWantToMove)) {
        blockIWantToMove = lastValidRope;
    }
    const blockInFront = offsetPos(blockIWantToMove, searchDirection, moveDirection);
    let success = false;
    if (blockInFront.typeId == canReplaceInFront || breakWhenPushed(blockInFront)) {
        if (blockInFront.typeId != canReplaceInFront)
            breakBlock(blockInFront);
        const targetPos = blockInFront.location;
        if (blockIWantToMove.typeId == canPassThrough) {
            level.setBlockPermutation(targetPos, addBehind);
            success = true;
        }
        else if (moveBlock(blockIWantToMove, targetPos)) {
            level.setBlockPermutation(blockIWantToMove.location, addBehind);
            success = true;
        }
    }
    //no depth bs for pulley
    else if (blockInFront.typeId == canPassThrough) {
        level.setBlockPermutation(blockIWantToMove.location, addBehind);
        success = true;
    }
    if (success) {
        //cant dynamically play the sound of a place block, except maybe if we were to place it with command?
        level.playSound("razz_sup.rope.place", blockInFront.center(), { pitch: 1, volume: 0.8 });
    }
    return success;
}
function canMove(block) {
    //if (block.typeId.endsWith("hanging_sign")) return true;
    return !isUnPushable(block) && !breakWhenPushed(block);
}
function shakeCamera(player, intensity, duration) {
    player.runCommand(`/camerashake add @s ${intensity} ${duration} positional`);
}
const isOnRope = new Set();
function isFeetBlockRope(entity) {
    const feetState = entity.dimension.getBlock(vecAdd(entity.location, 0, -0.1, 0));
    return !(!feetState || !isHorizontalRope(feetState));
}
function isHorizontalRope(block) {
    return block.typeId == "razz_sup:rope" /* SuppBlocks.Rope */ && !isAxisVertical(getADirection(block));
}
system.runInterval(() => {
    for (const id of isOnRope) {
        const entity = world.getEntity(id);
        if (!entity) {
            isOnRope.delete(id);
            continue;
        }
        if (entity.isSneaking) {
            continue;
        }
        if (entity instanceof Player) {
            shakeCamera(entity, 0.05, 0.5);
        }
    }
}, 10);
