import { suppEvents } from "../suppEventHandler";
import { BlockPermutation, Direction, system, world } from "@minecraft/server";
import { McBlocks } from "../reg/mcBlocks";
import { damageItemIfInSurvival, getPlayerHorizontalDir, isBlockSolid, isHoe, playSwingArm } from "../util/miscUtils";
import { flipDir, getClockwiseDir, offsetPos } from "../util/dirUtils";
import { SuppStates } from "../reg/suppStates";
import { needsSolidBlockBehind } from "../util/blockProperties";
suppEvents.subscribeOnNeighborChanged((event => {
    if (event.block.typeId == "razz_sup:raked_gravel" /* SuppBlocks.RakedGravel */) {
        if (event.fromDir == Direction.Down) {
            const below = event.block.below();
            if (below && below.isAir) {
                event.block.setType(McBlocks.Gravel);
            }
        }
        else if (event.fromDir == Direction.Up) {
            const above = event.block.above();
            if (above && !needsSolidBlockBehind(above.permutation)) {
                event.block.setType(McBlocks.Gravel);
            }
        }
    }
}));
export const RakedGravelComponent = {
    beforeOnPlayerPlace(event) {
        const above = event.block.above();
        if (isBlockSolid(above, Direction.Down)) {
            event.permutationToPlace = BlockPermutation.resolve(McBlocks.Gravel);
            return;
        }
        const dir = getPlayerHorizontalDir(event.player);
        event.permutationToPlace = getConnectedState(event.permutationToPlace, event.block, dir);
    }
};
function getRakeDirections(state) {
    const dir = state.permutation.getState(SuppStates.RakeDirection);
    switch (dir) {
        case "north_south":
            return [Direction.North, Direction.South];
        case "east_west":
            return [Direction.East, Direction.West];
        case "south_east":
            return [Direction.South, Direction.East];
        case "south_west":
            return [Direction.South, Direction.West];
        case "north_west":
            return [Direction.North, Direction.West];
        case "north_east":
            return [Direction.North, Direction.East];
    }
}
function encodeRakeDir(dir) {
    if (dir.length == 1) {
        if (dir[0] == Direction.North || dir[0] == Direction.South) {
            return "north_south";
        }
        else if (dir[0] == Direction.East || dir[0] == Direction.West) {
            return "east_west";
        }
    }
    else {
        if (dir.includes(Direction.South) && dir.includes(Direction.East)) {
            return "south_east";
        }
        else if (dir.includes(Direction.South) && dir.includes(Direction.West)) {
            return "south_west";
        }
        else if (dir.includes(Direction.North) && dir.includes(Direction.West)) {
            return "north_west";
        }
        else if (dir.includes(Direction.North) && dir.includes(Direction.East)) {
            return "north_east";
        }
    }
    console.error("Raked gravel direction not found");
    return "north_south";
}
function canConnectToBlock(state, dir) {
    if (state.typeId == "razz_sup:raked_gravel" /* SuppBlocks.RakedGravel */) {
        return getRakeDirections(state).includes(flipDir(dir));
    }
    return false;
}
function getConnectedState(perm, block, front) {
    const directionList = [];
    const level = block.dimension;
    const back = flipDir(front);
    if (canConnectToBlock(offsetPos(block, back), back)) {
        directionList.push(back);
    }
    else {
        directionList.push(front);
    }
    let side = getClockwiseDir(front);
    for (let i = 0; i < 2; i++) {
        const state = offsetPos(block, side);
        if (canConnectToBlock(state, side)) {
            directionList.push(side);
            break;
        }
        side = flipDir(side);
    }
    const value = encodeRakeDir(directionList);
    return perm.withState(SuppStates.RakeDirection, value);
}
world.beforeEvents.playerInteractWithBlock.subscribe((event) => {
    if (!event.isFirstEvent)
        return;
    const item = event.itemStack;
    if (!item)
        return;
    const block = event.block;
    const player = event.player;
    if (block.typeId == McBlocks.Gravel && isHoe(item)) {
        event.cancel = true;
        system.run(() => {
            const dir = getPlayerHorizontalDir(player);
            block.setPermutation(getConnectedState(BlockPermutation.resolve("razz_sup:raked_gravel" /* SuppBlocks.RakedGravel */), block, dir));
            player.dimension.playSound("use.gravel", block.center(), { volume: 0.8 });
            playSwingArm(player);
            damageItemIfInSurvival(player, item);
        });
    }
});
