import { directionState, getRightBlock, getLeftBlock } from '../util/globalVariables';

export class McfBlinds {
	constructor() {
		this.onPlace = this.onPlace.bind(this);
		this.onPlayerBreak = this.onPlayerBreak.bind(this);
		this.onPlayerInteract = this.onPlayerInteract.bind(this);
	}
	updatePlacedBlind(block, direction) {
		if (!block) return;
		block.setPermutation(block.permutation.withState("mr:top", block.above().hasTag(`${block.typeId}_${direction}`)));
	}
	updateNearestBlinds(block, direction, permutation) {
		const above = block.above();
		const below = block.below();
		const tag = `${permutation.type.id}_${direction}`;
		if (above.hasTag(tag)) this.updatePlacedBlind(above, direction);
		if (below.hasTag(tag)) this.updatePlacedBlind(below, direction);
	}
	toggleOpenState(block) {
		const direction = block.permutation.getState(directionState);
		const tag = `${block.typeId}_${direction}`;
		const visited = new Set();
		const stack = [block];
		const originX = block.x;
		const originY = block.y;
		const originZ = block.z;
		const currentState = block.permutation.getState("mr:close");
		const newState = !currentState;
		while (stack.length > 0) {
			const current = stack.pop();
			const key = `${current.x},${current.y},${current.z}`;
			if (visited.has(key)) continue;
			visited.add(key);
			if (Math.abs(current.x - originX) > 10 || Math.abs(current.y - originY) > 10 || Math.abs(current.z - originZ) > 10) continue;
			if (current.permutation.getState("mr:close") !== currentState) continue;
			current.setPermutation(current.permutation.withState("mr:close", newState));
			const neighbors = [
				current.above(),
				current.below(),
				getRightBlock(current, direction),
				getLeftBlock(current, direction)
			];
			for (const neighbor of neighbors) {
				if (!neighbor?.hasTag(tag)) continue;
				if (neighbor.permutation.getState("mr:close") === currentState) {
					stack.push(neighbor);
				}
			}
		}
	}
	onPlace(e) {
		const direction = e.block.permutation.getState(directionState);
		this.updatePlacedBlind(e.block, direction);
		this.updateNearestBlinds(e.block, direction, e.block.permutation);
	}
	onPlayerBreak(e) {
		const direction = e.brokenBlockPermutation.getState(directionState);
		this.updateNearestBlinds(e.block, direction, e.brokenBlockPermutation);
	}
	onPlayerInteract(e) {
		const { block, dimension } = e;
		this.toggleOpenState(block);
		dimension.playSound(block.permutation.getState("mr:close") ? "mr.blinds_open" : "mr.blinds_close", block.center());
	}
}