import { BlockPermutation, EquipmentSlot, GameMode, ItemEnchantableComponent, ItemStack } from '@minecraft/server';
import { airBlocks, directionState, getBackBlock, getRightBlock } from '../util/globalVariables';

const blockPartGetters = new Map([
	["2x1x1", (direction, block) => [
		{ target: getRightBlock(block, direction), part: 2 }
	]],
	["1x1x2", (direction, block) => [
		{ target: getBackBlock(block, direction), part: 2 }
	]],
	["1x2x1", (direction, block) => [
		{ target: block.above(), part: 2 }
	]],
	["2x1x2", (direction, block) => {
		const right = getRightBlock(block, direction);
		return [
			{ target: right, part: 2 },
			{ target: getBackBlock(right, direction), part: 3 },
			{ target: getBackBlock(block, direction), part: 4 }
		];
	}],
	["2x3x1", (direction, block) => {
		const blockAbove = block.above();
		const right = getRightBlock(block, direction);
		const rightAbove = right.above();
		return [
			{ target: blockAbove, part: 2 },
			{ target: blockAbove.above(), part: 3 },
			{ target: rightAbove.above(), part: 4 },
			{ target: rightAbove, part: 5 },
			{ target: right, part: 6 }
		];
	}],
	["2x2x2", (direction, block) => {
		const right = getRightBlock(block, direction);
		const back = getBackBlock(block, direction);
		const top = block.above();
		const topRight = getRightBlock(top, direction);
		const topBack = getBackBlock(top, direction);
		const topRightBack = getBackBlock(topRight, direction);
		return [
			{ target: right, part: 2 },
			{ target: getBackBlock(right, direction), part: 3 },
			{ target: back, part: 4 },
			{ target: top, part: 5 },
			{ target: topRight, part: 6 },
			{ target: topRightBack, part: 7 },
			{ target: topBack, part: 8 }
		];
	}]
]);
export class McfLargeBlockPlacer {
	constructor() {
		this.onPlace = this.onPlace.bind(this);
		this.beforeOnPlayerPlace = this.beforeOnPlayerPlace.bind(this);
	}
	setBlockParts(parts, id, direction) {
		parts.forEach(({ target, part }) => {
			const params = { [directionState]: direction, "mc:block_parts": part };
			target.setPermutation(BlockPermutation.resolve(id, params));
		});
	}
	beforeOnPlayerPlace(e, p) {
		const { block, permutationToPlace } = e;
		const direction = permutationToPlace.getState(directionState);
		const parts = blockPartGetters.get(p.params.size)(direction, block);
		if (!parts || !parts.every(({ target }) => airBlocks.includes(target.typeId))) e.cancel = true;
	}
	onPlace(e, p) {
		const { block } = e;
		const direction = block.permutation.getState(directionState);
		const parts = blockPartGetters.get(p.params.size)(direction, block);
		this.setBlockParts(parts, block.typeId, direction);
		block.setPermutation(block.permutation.withState("mc:block_parts", 1));
	}
}
export class McfBreakLargeBlock {
	onPlayerBreak(e) {
		if (e.player.matches({ gameMode: GameMode.Creative })) return;
		const item = e.player.getComponent("equippable").getEquipment(EquipmentSlot.Mainhand);
		const hasSilkTouch = item?.getComponent(ItemEnchantableComponent.componentId)?.getEnchantment("silk_touch");
		if (item && hasSilkTouch) return;
		e.dimension.spawnItem(new ItemStack(e.brokenBlockPermutation.type.id, 1), e.block.center());
	}
}