import { Block, BlockComponentOnPlaceEvent, BlockComponentPlayerDestroyEvent, world, } from "@minecraft/server";
import { namespace } from "../../../config/_config";
// This is a mess I know
export class ChairConnectBlock {
    static initialize() {
        // Register custom block component when the world is initialized
        world.beforeEvents.worldInitialize.subscribe((event) => {
            event.blockComponentRegistry.registerCustomComponent(`${namespace}:connect_chair`, {
                // Handle events before a player places a block
                beforeOnPlayerPlace: (event) => this.handleBeforePlacement(event),
                // Handle events when a player destroys a block
                onPlayerDestroy: (event) => {
                    if (event.destroyedBlockPermutation.getState(`${namespace}:connect`) != "sneaked")
                        this.handleBlockUpdate(event);
                },
                // // Handle events when a block is placed
                onPlace: (event) => {
                    if (event.block.permutation.getState(`${namespace}:connect`) != "sneaked")
                        this.handleBlockUpdate(event);
                },
            });
        });
        world.beforeEvents.playerBreakBlock.subscribe((event) => {
            if (event.block.above()?.hasTag("cc:cushion")) {
                event.block.dimension.runCommandAsync(`setblock ${event.block.location.x} ${event.block.location.y + 1}  ${event.block.location.z} air destroy`);
                event.cancel = true;
            }
        });
    }
    static handleBeforePlacement(event) {
        const block = event.block;
        const player = event.player;
        const placeBlock = event.permutationToPlace;
        if (!block || !player)
            return;
        const cardinalDirection = event.permutationToPlace.getState("minecraft:cardinal_direction");
        if (player.isSneaking) {
            event.permutationToPlace = event.permutationToPlace.withState(`${namespace}:connect`, "sneaked");
            return;
        }
        const blockLeft = this.validDirections(block, cardinalDirection, "left");
        const blockRight = this.validDirections(block, cardinalDirection, "right");
        const blockFront = this.validDirections(block, cardinalDirection, "front");
        const state = this.checkSurroundingBlocks(placeBlock, cardinalDirection, blockLeft, blockRight, blockFront);
        event.permutationToPlace = event.permutationToPlace.withState(`${namespace}:connect`, state);
    }
    static handleBlockUpdate(event) {
        let block;
        let cardinalDirection;
        let blockLeft;
        let blockRight;
        let blockFront;
        let blockType;
        let state;
        if (event instanceof BlockComponentOnPlaceEvent) {
            block = event.block;
            blockType = block.typeId;
            cardinalDirection = block.permutation.getState("minecraft:cardinal_direction");
            blockLeft = this.validDirections(block, cardinalDirection, "left");
            blockRight = this.validDirections(block, cardinalDirection, "right");
            blockFront = this.validDirections(block, cardinalDirection, "front");
        }
        if (event instanceof BlockComponentPlayerDestroyEvent) {
            const oldBlock = event.block;
            block = event.destroyedBlockPermutation;
            blockType = block.type.id;
            cardinalDirection = block.getState("minecraft:cardinal_direction");
            blockLeft = this.validDirections(oldBlock, cardinalDirection, "left");
            blockRight = this.validDirections(oldBlock, cardinalDirection, "right");
            blockFront = this.validDirections(oldBlock, cardinalDirection, "front");
            state = this.checkSurroundingBlocks(block, cardinalDirection, blockLeft, blockRight, blockFront);
        }
        if (blockLeft &&
            blockLeft.typeId === blockType &&
            blockLeft.permutation.getState(`${namespace}:connect`) != "sneaked") {
            cardinalDirection = blockLeft.permutation.getState("minecraft:cardinal_direction");
            const left = this.validDirections(blockLeft, cardinalDirection, "left");
            const right = this.validDirections(blockLeft, cardinalDirection, "right");
            const front = this.validDirections(blockLeft, cardinalDirection, "front");
            state = this.checkSurroundingBlocks(blockLeft, cardinalDirection, left, right, front);
            blockLeft.setPermutation(blockLeft.permutation.withState(`${namespace}:connect`, state));
        }
        if (blockRight &&
            blockRight.typeId === blockType &&
            blockRight.permutation.getState(`${namespace}:connect`) != "sneaked") {
            cardinalDirection = blockRight.permutation.getState("minecraft:cardinal_direction");
            const left = this.validDirections(blockRight, cardinalDirection, "left");
            const right = this.validDirections(blockRight, cardinalDirection, "right");
            const front = this.validDirections(blockRight, cardinalDirection, "front");
            state = this.checkSurroundingBlocks(blockRight, cardinalDirection, left, right, front);
            blockRight.setPermutation(blockRight.permutation.withState(`${namespace}:connect`, state));
        }
        if (blockFront &&
            blockFront.typeId === blockType &&
            blockFront.permutation.getState(`${namespace}:connect`) != "sneaked") {
            cardinalDirection = blockFront.permutation.getState("minecraft:cardinal_direction");
            const left = this.validDirections(blockFront, cardinalDirection, "left");
            const right = this.validDirections(blockFront, cardinalDirection, "right");
            const front = this.validDirections(blockFront, cardinalDirection, "front");
            state = this.checkSurroundingBlocks(blockFront, cardinalDirection, left, right, front);
            blockFront.setPermutation(blockFront.permutation.withState(`${namespace}:connect`, state));
        }
    }
    static checkSurroundingBlocks(block, blockDirection, left, right, front) {
        const leftDirection = left.permutation.getState("minecraft:cardinal_direction");
        const rightDirection = right.permutation.getState("minecraft:cardinal_direction");
        const frontDirection = front.permutation.getState("minecraft:cardinal_direction");
        const leftSneaking = left.permutation.getState(`${namespace}:connect`) == "sneaked";
        const rightSneaking = right.permutation.getState(`${namespace}:connect`) == "sneaked";
        const frontSneaking = front.permutation.getState(`${namespace}:connect`) == "sneaked";
        let blockType;
        let blockState;
        if (block instanceof Block) {
            blockType = block.typeId;
            blockState = block.permutation.getState(`${namespace}:connect`);
        }
        else {
            blockType = block.type.id;
            blockState = block.getState(`${namespace}:connect`);
        }
        const leftType = left.typeId;
        const rightType = right.typeId;
        const frontType = front.typeId;
        const leftState = left.permutation.getState(`${namespace}:connect`);
        const rightState = right.permutation.getState(`${namespace}:connect`);
        const frontState = front.permutation.getState(`${namespace}:connect`);
        // corner_ne
        if (blockState === "corner_ne") {
            if (leftDirection === blockDirection &&
                frontDirection === "east" &&
                !leftSneaking &&
                !frontSneaking) {
                return "corner_ne";
            }
            if (rightDirection === blockDirection &&
                frontDirection === "north" &&
                !rightSneaking &&
                !frontSneaking) {
                return "corner_ne";
            }
        }
        // corner_se
        if (blockState === "corner_se") {
            if (rightDirection === blockDirection &&
                frontDirection === "south" &&
                !rightSneaking &&
                !frontSneaking) {
                return "corner_se";
            }
            if (leftDirection === blockDirection &&
                frontDirection === "east" &&
                !leftSneaking &&
                !frontSneaking) {
                return "corner_se";
            }
        }
        // corner_sw
        if (blockState === "corner_sw") {
            if (rightDirection === blockDirection &&
                frontDirection === "west" &&
                !rightSneaking &&
                !frontSneaking) {
                return "corner_sw";
            }
            if (leftDirection === blockDirection &&
                frontDirection === "south" &&
                !leftSneaking &&
                !frontSneaking) {
                return "corner_sw";
            }
        }
        // corner_nw
        if (blockState === "corner_nw") {
            if (leftDirection === blockDirection &&
                frontDirection === "north" &&
                !leftSneaking &&
                !frontSneaking) {
                return "corner_nw";
            }
            if (rightDirection === blockDirection &&
                frontDirection === "west" &&
                !rightSneaking &&
                !frontSneaking) {
                return "corner_nw";
            }
        }
        if (blockType === frontType) {
            if (blockState === "inner" && blockDirection !== frontDirection && !frontSneaking) {
                return "inner";
            }
        }
        // north east
        if (blockType === rightType &&
            (leftDirection !== blockDirection || blockType !== leftType || leftSneaking)) {
            if (blockDirection === "north" && rightDirection === "east" && rightState === "inner") {
                return "single";
            }
        }
        // north west
        if (blockType === leftType &&
            (rightDirection !== blockDirection || blockType !== rightType || rightSneaking)) {
            if (blockDirection === "north" && leftDirection === "west" && leftState === "inner") {
                return "single";
            }
        }
        // east south
        if (blockType === rightType &&
            (leftDirection !== blockDirection || blockType !== leftType || leftSneaking)) {
            if (blockDirection === "east" && rightDirection === "south" && rightState === "inner") {
                return "single";
            }
        }
        // east north
        if (blockType === leftType &&
            (rightDirection !== blockDirection || blockType !== rightType || rightSneaking)) {
            if (blockDirection === "east" && leftDirection === "north" && leftState === "inner") {
                return "single";
            }
        }
        // south west
        if (blockType === rightType &&
            (leftDirection !== blockDirection || blockType !== leftType || leftSneaking)) {
            if (blockDirection === "south" && rightDirection === "west" && rightState === "inner") {
                return "single";
            }
        }
        // south east
        if (blockType === leftType &&
            (rightDirection !== blockDirection || blockType !== rightType || rightSneaking)) {
            if (blockDirection === "south" && leftDirection === "east" && leftState === "inner") {
                return "single";
            }
        }
        // west north
        if (blockType === rightType &&
            (leftDirection !== blockDirection || blockType !== leftType || leftSneaking)) {
            if (blockDirection === "west" && rightDirection === "north" && rightState === "inner") {
                return "single";
            }
        }
        // west south
        if (blockType === leftType &&
            (rightDirection !== blockDirection || blockType !== rightType || rightSneaking)) {
            if (blockDirection === "west" && leftDirection === "south" && leftState === "inner") {
                return "single";
            }
        }
        if (blockType === rightType &&
            blockType !== leftType &&
            blockType === frontType &&
            !frontSneaking &&
            !rightSneaking &&
            !frontState.includes("corner") &&
            !rightState.includes("corner")) {
            // for all corners
            if (blockDirection === "north" && rightDirection === "east" && frontDirection === "west") {
                return "corner_nw";
            }
            if (blockDirection === "east" && rightDirection === "south" && frontDirection === "north") {
                return "corner_ne";
            }
            if (blockDirection === "south" && rightDirection === "west" && frontDirection === "east") {
                return "corner_se";
            }
            if (blockDirection === "west" && rightDirection === "north" && frontDirection === "south") {
                return "corner_sw";
            }
        }
        if (blockType === leftType &&
            blockType === rightType &&
            !leftSneaking &&
            !rightSneaking &&
            !rightState.includes("corner") &&
            !leftState.includes("corner")) {
            if (blockDirection === leftDirection && blockDirection === rightDirection) {
                return "inner";
            }
        }
        if (blockType === leftType &&
            blockType === frontType &&
            !leftSneaking &&
            !frontSneaking &&
            !leftState.includes("corner") &&
            !frontState.includes("corner")) {
            if (blockDirection === "north") {
                if (leftDirection === blockDirection && frontDirection === "east") {
                    return "corner_ne";
                }
            }
            if (blockDirection === "south") {
                if (leftDirection === blockDirection && frontDirection === "west") {
                    return "corner_sw";
                }
            }
            if (blockDirection === "east") {
                if (leftDirection === blockDirection && frontDirection === "south") {
                    return "corner_se";
                }
            }
            if (blockDirection === "west") {
                if (leftDirection === blockDirection && frontDirection === "north") {
                    return "corner_nw";
                }
            }
        }
        if (blockType === rightType &&
            blockType === frontType &&
            !frontSneaking &&
            !rightSneaking &&
            !frontState.includes("corner") &&
            !rightState.includes("corner")) {
            if (blockDirection === "north") {
                if (rightDirection === blockDirection && frontDirection === "west") {
                    return "corner_nw";
                }
            }
            if (blockDirection === "south") {
                if (rightDirection === blockDirection && frontDirection === "east") {
                    return "corner_se";
                }
            }
            if (blockDirection === "east") {
                if (rightDirection === blockDirection && frontDirection === "north") {
                    return "corner_ne";
                }
            }
            if (blockDirection === "west") {
                if (rightDirection === blockDirection && frontDirection === "south") {
                    return "corner_sw";
                }
            }
        }
        if (rightType == blockType && leftType == blockType && !leftSneaking && !rightSneaking) {
            const leftTargetDirections = [blockDirection];
            const rightTargetDirections = [blockDirection];
            switch (blockDirection) {
                case "north":
                    leftTargetDirections.push("west");
                    rightTargetDirections.push("east");
                    break;
                case "south":
                    leftTargetDirections.push("east");
                    rightTargetDirections.push("west");
                    break;
                case "east":
                    leftTargetDirections.push("north");
                    rightTargetDirections.push("south");
                    break;
                case "west":
                    leftTargetDirections.push("south");
                    rightTargetDirections.push("north");
                    break;
            }
            if ((blockDirection == leftDirection ||
                (leftState != "inner" && leftTargetDirections.includes(leftDirection))) &&
                (blockDirection == rightDirection ||
                    (rightState != "inner" && rightTargetDirections.includes(rightDirection))))
                return "inner";
        }
        let leftTargetDirection = "north";
        let rightTargetDirection = "north";
        let leftCornerState = "";
        let rightCornerState = "";
        switch (blockDirection) {
            case "north":
                leftTargetDirection = "west";
                rightTargetDirection = "east";
                leftCornerState = "corner_nw";
                rightCornerState = "corner_ne";
                break;
            case "south":
                leftTargetDirection = "east";
                rightTargetDirection = "west";
                leftCornerState = "corner_se";
                rightCornerState = "corner_sw";
                break;
            case "east":
                leftTargetDirection = "north";
                rightTargetDirection = "south";
                leftCornerState = "corner_ne";
                rightCornerState = "corner_se";
                break;
            case "west":
                leftTargetDirection = "south";
                rightTargetDirection = "north";
                leftCornerState = "corner_sw";
                rightCornerState = "corner_nw";
                break;
        }
        if ((leftType != blockType || leftDirection != blockDirection || leftSneaking) &&
            rightType == blockType &&
            (rightDirection == blockDirection || rightDirection == rightTargetDirection) &&
            !rightSneaking &&
            !(rightState.includes("corner") && rightCornerState != rightState))
            return "end_left";
        if ((rightType != blockType || rightDirection != blockDirection || rightSneaking) &&
            leftType == blockType &&
            (leftDirection == blockDirection || leftDirection == leftTargetDirection) &&
            !leftSneaking &&
            !(leftState.includes("corner") && leftCornerState != leftState))
            return "end_right";
        return "single";
    }
    static validDirections(block, direction, relativeDirection) {
        if (direction === "north") {
            if (relativeDirection === "left") {
                return block.west();
            }
            if (relativeDirection === "right") {
                return block.east();
            }
            if (relativeDirection === "front") {
                return block.south();
            }
        }
        if (direction === "south") {
            if (relativeDirection === "left") {
                return block.east();
            }
            if (relativeDirection === "right") {
                return block.west();
            }
            if (relativeDirection === "front") {
                return block.north();
            }
        }
        if (direction === "east") {
            if (relativeDirection === "left") {
                return block.north();
            }
            if (relativeDirection === "right") {
                return block.south();
            }
            if (relativeDirection === "front") {
                return block.west();
            }
        }
        if (direction === "west") {
            if (relativeDirection === "left") {
                return block.south();
            }
            if (relativeDirection === "right") {
                return block.north();
            }
            if (relativeDirection === "front") {
                return block.east();
            }
        }
    }
}
