import * as SERVER from '@minecraft/server';
import * as UI from '@minecraft/server-ui';

// Subscribe to events to run code when specific in game actions occur
SERVER.system.afterEvents.scriptEventReceive.subscribe((data) => {
	if (data.id === "vc:observer.setfilter") {
		let player = data.sourceEntity; //the player
		let block = player.getBlockFromViewDirection().block; //the hopper
		let blockentity = block.dimension.getEntitiesAtBlockLocation(block.location)[0]; //the hopper entity
		let item = player.getComponent("equippable").getEquipment("Mainhand"); //the new filter
		if (!item) item = new SERVER.ItemStack('minecraft:air', 1)
		if (block.typeId == "vc:advanced_observer") {
			if (block.permutation.getState("vc:changeable") == false) {
				setPermutation(block, "vc:changeable", true)
				SERVER.system.runTimeout(() => { setPermutation(block, "vc:changeable", false) }, 40)
				if (blockentity.nameTag.startsWith('specfilt-')) advancedFilterConfig(player, blockentity, true)
				else player.runCommand(`title @s actionbar §7Block filter is §f§l${blockentity.nameTag}`);
			} else {
				if (item.typeId == 'vc:advanced_filter') {
					advancedFilterConfig(player, blockentity)
					return;
				}
				if (blockentity.nameTag.startsWith('specfilt-')) blockentity.dimension.spawnItem(new SERVER.ItemStack('vc:advanced_filter', 1), blockentity.location);
				setPermutation(block, "vc:changeable", false)
				blockentity.nameTag = `${item.typeId}`;
				player.runCommand(`title @s actionbar §7Set block filter to §f§l${item.typeId}`);
				blockentity.runCommand(`playsound advanced_hopper.change @a[r=15] `)
			}
		}
	};
	if (data.id === "vc:observer.tickFilter") {
		let entity = data.sourceEntity; //the hopper entity
		if (entity == undefined) {
			console.warn("No Source Entity");
			SERVER.world.sendMessage("A observer has failed to filter");
			return;
		}
		let filter = entity.nameTag;
		const block = entity.dimension.getBlock(entity.location);
		let detection = block.below(1);
		if (block.permutation.getState("minecraft:facing_direction") == "north") detection = block.north(1)
		if (block.permutation.getState("minecraft:facing_direction") == "east") detection = block.east(1)
		if (block.permutation.getState("minecraft:facing_direction") == "south") detection = block.south(1)
		if (block.permutation.getState("minecraft:facing_direction") == "west") detection = block.west(1)
		if (block.permutation.getState("minecraft:facing_direction") == "up") detection = block.above(1)

		let sucess = (detection.typeId == entity.nameTag);
		if (entity.nameTag.startsWith('specfilt-equal')) { sucess = detection.typeId == entity.nameTag.replace('specfilt-equal', '') }
		if (entity.nameTag.startsWith('specfilt-startWith')) { sucess = detection.typeId.startsWith(entity.nameTag.replace('specfilt-startWith', '')) }
		if (entity.nameTag.startsWith('specfilt-endWith')) { sucess = detection.typeId.endsWith(entity.nameTag.replace('specfilt-endWith', '')) }
		if (entity.nameTag.startsWith('specfilt-anyOf')) {
			var ids = entity.nameTag.replace('specfilt-anyOf', '').split(',');
			ids.forEach((id) => {
				if (detection.typeId == id) sucess = true
			})
		}
		if (entity.nameTag.startsWith('specfilt-blockstate')) {
			var results = entity.nameTag.replace('specfilt-blockstate', '').split('||')
			var state = detection.permutation.getState(results[0])
			if (state != undefined) switch (results[1]) {
				case '>':
					results[2] = Number(results[2])
					sucess = (state > results[2])
					break;
				case '<':
					results[2] = Number(results[2])
					sucess = (state < results[2])
					break;
				case '=':
					sucess = (state.toString() == results[2].toString())
					break;
			}
		}
		setPermutation(block, 'vc:lit_bit', sucess)
		if (sucess) {
			if (block.permutation.getState("minecraft:facing_direction") == "north") turnOnRedstone(block.north(-1), "north")
			if (block.permutation.getState("minecraft:facing_direction") == "east") turnOnRedstone(block.east(-1), "east")
			if (block.permutation.getState("minecraft:facing_direction") == "south") turnOnRedstone(block.south(-1), "south")
			if (block.permutation.getState("minecraft:facing_direction") == "west") turnOnRedstone(block.west(-1), "west")
		}
	}
});
function advancedFilterConfig(player, blockentity, getDefs) {
	const pullitem = blockentity.nameTag
	let defSelect = 0;
	let defText = '';
	let defState = '';
	if (getDefs) {
		if (pullitem.startsWith('specfilt-equal')) { defSelect = 0; defText = pullitem.replace('specfilt-equal', '') }
		if (pullitem.startsWith('specfilt-startWith')) { defSelect = 1; defText = pullitem.replace('specfilt-startWith', '') }
		if (pullitem.startsWith('specfilt-endWith')) { defSelect = 2; defText = pullitem.replace('specfilt-endWith', '') }
		if (pullitem.startsWith('specfilt-anyOf')) { defText = pullitem.replace('specfilt-anyOf', '') }
		if (pullitem.startsWith('specfilt-blockstate')) {
			var results = pullitem.replace('specfilt-blockstate', '').split('||')
			defSelect = (results[1] == '>' ? 1 : results[1] == '<' ? 2 : '=')
			defText = results[2]
			defState = results[0]
		}
	}


	const main = new UI.ActionFormData()
		.title('Set Filter')
		.body('Check if...')
		.button('Block Name...')
		.button('Block State...')
		.button('Multible Blocks...');
	main.show(player).then((ee) => {
		if (ee.selection == 0) {
			const oplist = ['Equals', 'Starts with', 'Ends with']
			let popUp = new UI.ModalFormData()
				.title("Set Filter")
				.dropdown('Block name...', oplist, defSelect)
				.textField("", "Value", defText);

			popUp.show(player).then((r) => {
				if (r.canceled) return;
				if (r.formValues[0] == 0) blockentity.nameTag = `specfilt-equal${r.formValues[1]}`
				if (r.formValues[0] == 1) blockentity.nameTag = `specfilt-startWith${r.formValues[1]}`
				if (r.formValues[0] == 2) blockentity.nameTag = `specfilt-endWith${r.formValues[1]}`
				player.runCommand(`title @s actionbar §7Set block filter to §fName ${(r.formValues[0] == 1 ? 'starts with' : r.formValues[0] == 2 ? 'ends with' : 'equals')} §l${r.formValues[1]}`);
				if (item.amount == 1) item = new SERVER.ItemStack("minecraft:air", 2)
				item.amount += -1
				player.getComponent("equippable").setEquipment("Mainhand", item);
			}).catch((e) => {
				console.error(e, e.stack);
			})
		}
		else if (ee.selection == 1) {
			const oplist = ['Equals', 'Greater Than', 'Less Than']
			let popUp = new UI.ModalFormData()
				.title("Set Filter")
				.textField("", "Block State", defState)
				.dropdown('is...', oplist, defSelect)
				.textField("", "Value", defText);

			popUp.show(player).then((r) => {
				if (r.canceled) return;
				blockentity.nameTag = `specfilt-blockstate${r.formValues[0]}||${(r.formValues[1] == 1 ? '>' : r.formValues[1] == 2 ? '<' : '=')}||${r.formValues[2]}`
				player.runCommand(`title @s actionbar §7Set block filter to §fBlock State: §l${r.formValues[0]} is ${(r.formValues[1] == 1 ? '>' : r.formValues[1] == 2 ? '<' : '=')} ${r.formValues[2]}`);
				if (item.amount == 1) item = new SERVER.ItemStack("minecraft:air", 2)
				item.amount += -1
				player.getComponent("equippable").setEquipment("Mainhand", item);
			}).catch((e) => {
				console.error(e, e.stack);
			})
		}
		else {
			let popUp = new UI.ModalFormData()
				.title("Set Filter")
				.textField("Blocks to detect for (seperate by ',')", "minecraft:air,vc:glowing_mushroom", defText)

			popUp.show(player).then((r) => {
				if (r.canceled) return;
				blockentity.nameTag = `specfilt-anyOf${r.formValues[0]}`
				player.runCommand(`title @s actionbar §7Set block filter to §fAny Of: §l${r.formValues[0]}`);
				if (item.amount == 1) item = new SERVER.ItemStack("minecraft:air", 2)
				item.amount += -1
				player.getComponent("equippable").setEquipment("Mainhand", item);
			}).catch((e) => {
				console.error(e, e.stack);
			})
		}
	})
}
// See more at https://wiki.bedrock.dev/scripting/script-server.html

function setPermutation(block, stateAdd, stateValue) { //stole this from someone :evil:
	const result = block.permutation.getAllStates();
	result[stateAdd] = stateValue;
	block.setPermutation(SERVER.BlockPermutation.resolve(block.typeId, result));
}
function turnOnRedstone(block, direction) {
	if (block.typeId == 'minecraft:unpowered_repeater' && block.permutation.getState("minecraft:cardinal_direction") == direction) {
		block.setType('minecraft:powered_repeater')
		setPermutation(block, 'minecraft:cardinal_direction', direction)
	}
	else if (block.typeId == 'minecraft:redstone_wire') {
		setPermutation(block, 'redstone_signal', 15)
	}
	else if (block.typeId == 'minecraft:redstone_torch' && block.permutation.getState("torch_facing_direction") == direction) {
		block.setType('minecraft:unlit_redstone_torch')
		setPermutation(block, 'torch_facing_direction', direction)
	}
}