import { world } from '@minecraft/server';

class redstoneManager {
	//all the power states below handle the tracking for the toggle trapdoor(s), avoiding state changes causing observer outputs
	static worldDynamicProperty = "cloudDoorPowerStates";

	static loadPowerStates() {
		const statesString = world.getDynamicProperty(this.worldDynamicProperty);
		if (statesString) {
			return new Map(JSON.parse(statesString));
		}
		return new Map();
	}

	static savePowerStates(powerStates) {
		world.setDynamicProperty(this.worldDynamicProperty, JSON.stringify([...powerStates]));
	}

	static getPowerState(block) {
		const blockKey = `${block.x},${block.y},${block.z}`;
		const powerStates = this.loadPowerStates();
		return powerStates.get(blockKey) || false;
	}

	static setPowerState(block, powered) {
		const blockKey = `${block.x},${block.y},${block.z}`;
		const powerStates = this.loadPowerStates();
		powerStates.set(blockKey, powered);
		this.savePowerStates(powerStates);
	}

	static deletePowerState(block) {
		const blockKey = `${block.x},${block.y},${block.z}`;
		const powerStates = this.loadPowerStates();
		powerStates.delete(blockKey);
		this.savePowerStates(powerStates);
	}

	//this is the system to check for power around the block, not perfect, could use more granular defining like a torch above shouldn't power but does
	static powered(block) {
		if (!block.hasTag("cloud:is_door")) return;
		let powered = false;
		let above = undefined;
		try {
			above = block.above(1);
		} catch  {}
		let below = undefined;
		try {
			below = block.below(1);
		} catch  {}
		let north = undefined;
		try {
			north = block.north(1);
		} catch  {}
		let south = undefined;
		try {
			south = block.south(1);
		} catch  {}
		let east = undefined;
		try {
			east = block.east(1);
		} catch  {}
		let west = undefined;
		try {
			west = block.west(1);
		} catch  {}
		const sides = [
			above,
			below,
			north,
			south,
			east,
			west
		];
		for (const side of sides){
			if (side != undefined && side.getRedstonePower() > 0) powered = true;
		}
		return powered;
	}
	//after event to trigger the custom component events inside the onTick
	static redstonePowerAfterEvent(block, event) {
		if (!block.hasTag("cloud:is_door")) return;
		const powered = this.powered(block);
		const wasPowered = this.getPowerState(block);

		if (block.hasTag("cloud:toggle")) {
			if (powered && !wasPowered) {
				if (event.toggle != undefined) event.toggle(block);
			}
			this.setPowerState(block, powered);
			return;
		}

		if (powered && !wasPowered) {
			event.code(block);
		} else if (!powered && wasPowered) {
			if (event.unpowered != undefined) event.unpowered(block);
		}

		this.setPowerState(block, powered);
	}
}

function playOpenSound(wooden, dim, loc) {
	let doorSounds;
	if (wooden) {
		doorSounds = ["random.door_open", "open.wooden_trapdoor"];
	} else {
		doorSounds = ["open.iron_door", "open.iron_trapdoor"];
	}
	const sound = doorSounds[Math.floor(Math.random() * doorSounds.length)];
	dim.playSound(sound, loc, {
		pitch: 0.9,
		volume: 0.9,
	});
}

function playCloseSound(wooden, dim, loc) {
	let doorSounds;
	if (wooden) {
		doorSounds = ["random.door_close", "close.wooden_trapdoor"];
	} else {
		doorSounds = ["close.iron_door", "close.iron_trapdoor"];
	}
	const sound = doorSounds[Math.floor(Math.random() * doorSounds.length)];
	dim.playSound(sound, loc, {
		pitch: 0.9,
		volume: 0.9,
	});
}

export {redstoneManager,playOpenSound,playCloseSound};
