import { world, system, BlockPermutation } from "@minecraft/server";
import "./main-1.js";

const connectedCouchTypes = new Set([
    "furnideco:rustic.acacia.sofa", "furnideco:rustic.bamboo.sofa", "furnideco:rustic.birch.sofa",
    "furnideco:rustic.cherry.sofa", "furnideco:rustic.crimson.sofa", "furnideco:rustic.dark_oak.sofa",
    "furnideco:rustic.jungle.sofa", "furnideco:rustic.mangrove.sofa", "furnideco:rustic.oak.sofa",
    "furnideco:rustic.spruce.sofa", "furnideco:rustic.warped.sofa", "furnideco:rustic.acacia.cabinet", "furnideco:rustic.bamboo.cabinet",
    "furnideco:rustic.birch.cabinet", "furnideco:rustic.cherry.cabinet", "furnideco:rustic.crimson.cabinet",
    "furnideco:rustic.dark_oak.cabinet", "furnideco:rustic.jungle.cabinet", "furnideco:rustic.mangrove.cabinet",
    "furnideco:rustic.oak.cabinet", "furnideco:rustic.spruce.cabinet", "furnideco:rustic.warped.cabinet",
    "furnideco:rustic.acacia.coffee_table", "furnideco:rustic.bamboo.coffee_table", "furnideco:rustic.birch.coffee_table",
    "furnideco:rustic.cherry.coffee_table", "furnideco:rustic.crimson.coffee_table", "furnideco:rustic.dark_oak.coffee_table",
    "furnideco:rustic.jungle.coffee_table", "furnideco:rustic.mangrove.coffee_table", "furnideco:rustic.oak.coffee_table",
    "furnideco:rustic.spruce.coffee_table", "furnideco:rustic.warped.coffee_table", "furnideco:rustic.curtain"
]);

world.beforeEvents.playerBreakBlock.subscribe((eventData) => {
    const { block, dimension } = eventData;
    if (connectedCouchTypes.has(block.typeId)) {
        breakConnected(dimension, block);
    }
});

world.beforeEvents.worldInitialize.subscribe(eventData => {
    eventData.blockComponentRegistry.registerCustomComponent('furnideco:connected_place', {
        onPlace(event) {
            const block = event.block;
            const dimension = event.dimension;
            if (connectedCouchTypes.has(block.typeId)) {
                placeConnected(dimension, block);
            }
        }
    });
});

function isConnected(adjacentBlock, block) {
    return adjacentBlock.typeId === block.typeId &&
        adjacentBlock.permutation.getState('minecraft:cardinal_direction') === block.permutation.getState('minecraft:cardinal_direction');
}

function getAdjacentBlocks(dimension, block) {
    return {
        north: dimension.getBlock(block.north()),
        south: dimension.getBlock(block.south()),
        east: dimension.getBlock(block.east()),
        west: dimension.getBlock(block.west())
    };
}

function getSecondAdjacentBlocks(dimension, block) {
    return {
        north: dimension.getBlock(block.north().north()),
        south: dimension.getBlock(block.south().south()),
        east: dimension.getBlock(block.east().east()),
        west: dimension.getBlock(block.west().west())
    };
}

function placeConnected(dimension, block) {
    const adjacentBlocks = getAdjacentBlocks(dimension, block);
    const connectedSides = [];

    // Get the player's facing direction when placing the block
    const player = dimension.getPlayers()[0]; // Assumes single player, adjust if needed
    const playerDirection = getPlayerDirection(player);

    for (const [direction, adjacentBlock] of Object.entries(adjacentBlocks)) {
        if (isConnected(adjacentBlock, block)) {
            connectedSides.push(direction);
            updateAdjacentBlock(adjacentBlock, direction, getAdjacentBlocks(dimension, adjacentBlock), getSecondAdjacentBlocks(dimension, adjacentBlock));
        }
    }

    updatePlacedBlock(block, connectedSides, playerDirection);
}

function updateAdjacentBlock(block, connectedDirection, adjacentBlocks, secondAdjacentBlocks) {
    const oppositeDirection = {
        north: 'south',
        south: 'north',
        east: 'west',
        west: 'east'
    };

    const otherConnectedSide = Object.entries(adjacentBlocks).find(([dir, adjBlock]) =>
        dir !== oppositeDirection[connectedDirection] && isConnected(adjBlock, block)
    );

    const furtherConnected = secondAdjacentBlocks[connectedDirection] &&
        isConnected(secondAdjacentBlocks[connectedDirection], block);

    let newConnectionState;

    if (furtherConnected || otherConnectedSide) {
        newConnectionState = 'connected_middle';
    } else {
        const blockFacingDirection = block.permutation.getState('minecraft:cardinal_direction');
        newConnectionState = determineConnectionState(blockFacingDirection, connectedDirection);
    }

    // Get the current cardinal direction
    const currentDirection = block.permutation.getState('minecraft:cardinal_direction');

    // Set the new permutation while preserving the cardinal direction
    block.setPermutation(BlockPermutation.resolve(block.typeId, {
        'furnideco:connected_left': newConnectionState === 'connected_left' ? 1 : 0,
        'furnideco:connected_middle': newConnectionState === 'connected_middle' ? 1 : 0,
        'furnideco:connected_right': newConnectionState === 'connected_right' ? 1 : 0,
        'furnideco:default': newConnectionState === 'default' ? 1 : 0,
        'minecraft:cardinal_direction': currentDirection
    }));
}

function determineConnectionState(blockFacingDirection, connectedDirection) {
    const connectionMap = {
        north: {
            east: 'connected_right',
            west: 'connected_left'
        },
        south: {
            east: 'connected_left',
            west: 'connected_right'
        },
        east: {
            north: 'connected_left',
            south: 'connected_right'
        },
        west: {
            north: 'connected_right',
            south: 'connected_left'
        }
    };

    return connectionMap[blockFacingDirection]?.[connectedDirection] || 'default';
}

function updatePlacedBlock(block, connectedSides, playerDirection) {
    let newConnectionState;

    if (connectedSides.length === 0) {
        newConnectionState = 'default';
    } else if (connectedSides.length === 1) {
        newConnectionState = determineConnectionState(playerDirection, connectedSides[0]);
    } else {
        newConnectionState = 'connected_middle';
    }

    block.setPermutation(BlockPermutation.resolve(block.typeId, {
        'furnideco:connected_left': newConnectionState === 'connected_right' ? 1 : 0,
        'furnideco:connected_middle': newConnectionState === 'connected_middle' ? 1 : 0,
        'furnideco:connected_right': newConnectionState === 'connected_left' ? 1 : 0,
        'furnideco:default': newConnectionState === 'default' ? 1 : 0,
        'minecraft:cardinal_direction': playerDirection
    }));
}

function getPlayerDirection(player) {
    const rotation = player.getRotation().y;
    if (rotation >= -45 && rotation < 45) return 'south';
    if (rotation >= 45 && rotation < 135) return 'west';
    if (rotation >= 135 || rotation < -135) return 'north';
    return 'east';
}

function breakConnected(dimension, block) {
    const directions = ['north', 'south', 'east', 'west'];

    for (const direction of directions) {
        const adjacentBlock = dimension.getBlock(block[direction]());
        if (isConnected(adjacentBlock, block)) {
            system.runTimeout(() => {
                const cardinalDirection = adjacentBlock.permutation.getState('minecraft:cardinal_direction');
                let newState;

                // Check connections on both sides of the adjacent block
                const oppositeDirection = getOppositeDirection(direction);
                const hasConnectionInDirection = isConnected(dimension.getBlock(adjacentBlock[direction]()), adjacentBlock);
                const hasConnectionInOppositeDirection = isConnected(dimension.getBlock(adjacentBlock[oppositeDirection]()), adjacentBlock);

                if (hasConnectionInDirection && hasConnectionInOppositeDirection) {
                    newState = 'connected_middle';
                } else if (hasConnectionInDirection || hasConnectionInOppositeDirection) {
                    const connectedDirection = hasConnectionInDirection ? direction : oppositeDirection;
                    const relativeDirection = getRelativeDirection(cardinalDirection, connectedDirection);
                    newState = relativeDirection === 'left' ? 'connected_right' : 'connected_left';
                } else {
                    newState = 'default';
                }

                adjacentBlock.setPermutation(BlockPermutation.resolve(adjacentBlock.typeId, {
                    'furnideco:connected_left': newState === 'connected_left' ? 1 : 0,
                    'furnideco:connected_middle': newState === 'connected_middle' ? 1 : 0,
                    'furnideco:connected_right': newState === 'connected_right' ? 1 : 0,
                    'furnideco:default': newState === 'default' ? 1 : 0,
                    'minecraft:cardinal_direction': cardinalDirection
                }));
            }, 1);
        }
    }
}

function getOppositeDirection(direction) {
    const oppositeDirections = {
        north: 'south',
        south: 'north',
        east: 'west',
        west: 'east'
    };
    return oppositeDirections[direction];
}

function getRelativeDirection(cardinalDirection, connectionDirection) {
    const directionMap = {
        north: { east: 'right', west: 'left' },
        south: { east: 'left', west: 'right' },
        east: { north: 'left', south: 'right' },
        west: { north: 'right', south: 'left' }
    };
    return directionMap[cardinalDirection]?.[connectionDirection] || 'default';
}