import { system, world, BlockPermutation, Direction, EntityDamageCause, EquipmentSlot, GameMode, ItemStack } from "@minecraft/server";
import * as defaultWorldArrays from "../arrays/default_world_arrays.js"
import * as blockArrays from "../arrays/block_arrays.js"
import * as itemArrays from "../arrays/item_arrays.js"
import * as itemUtilities from "../utilities/item_utilities.js"
import * as mathUtilities from "../utilities/math_utilities.js"
import * as worldUtilities from "../utilities/world_utilities.js"

world.beforeEvents.playerInteractWithBlock.subscribe(event => {
	const {block,blockFace,itemStack,player} = event;
	if (!itemStack) return;
	const item = itemStack.typeId;
	const array = defaultWorldArrays;
	const itemNamespaceSplit = item.split(":");
	if (item.startsWith("minecraft:")) {
		if (item=="minecraft:bone_meal"&&block.typeId=="minecraft:dirt") {
			const dimension = block.dimension;
			const blockAbove = dimension.getBlock(block.above(1));
			if (!blockAbove.isAir) return;
			const offsets = [
				{x:1,y:0,z:0},
				{x:-1,y:0,z:0},
				{x:0,y:1,z:0},
				{x:0,y:-1,z:0},
				{x:0,y:0,z:1},
				{x:0,y:0,z:-1},
				{x:1,y:-1,z:0},
				{x:-1,y:-1,z:0},
				{x:0,y:-1,z:1},
				{x:0,y:-1,z:-1},
				{x:1,y:1,z:0},
				{x:-1,y:1,z:0},
				{x:0,y:1,z:1},
				{x:0,y:1,z:-1},
				{x:1,y:0,z:1},
				{x:-1,y:0,z:1},
				{x:-1,y:0,z:-1},
				{x:1,y:0,z:-1}
			];
			const adjacentGrassBlocks = offsets.some(offset=>{
				const adjacent = dimension.getBlock({
					x:block.location.x+offset.x,
					y:block.location.y+offset.y,
					z:block.location.z+offset.z
				});
				return adjacent.typeId=="minecraft:grass_block";
			});
			if (!adjacentGrassBlocks) return;
			system.run(() => {
				itemUtilities.itemDecrementStack(itemStack,player);
				block.dimension.spawnParticle("minecraft:crop_growth_emitter",{x:block.center().x,y:block.center().y+1,z:block.center().z});
				player.playSound("item.bone_meal.use",{location:block.center()});
				block.setType("minecraft:grass_block");
			});
		}
	}
	if (array.addonNamespaces.some(prefix => item.startsWith(prefix))) {
		if (itemArrays.sconceItemsTypeId.includes(item)||itemArrays.sconceItemsTags.some(tag=>itemStack.hasTag(tag))) {
			if (blockFace=="Down") return event.cancel = true;
		}
		if (item.includes("_slab")) {
			const dimension = block.dimension;
			const blockAbove = dimension.getBlock(block.above(1));
			const blockBelow = dimension.getBlock(block.below(1));
			const blockNorth = dimension.getBlock(block.north(1));
			const blockSouth = dimension.getBlock(block.south(1));
			const blockWest = dimension.getBlock(block.west(1));
			const blockEast = dimension.getBlock(block.east(1));
			const verticalHalf = block.permutation.getState("minecraft:vertical_half");
			const removeSlab = itemNamespaceSplit[1].split("_slab");
			let blockId = block.typeId;
			let blockLocate = block;
			function runSystemBlockSlab() {
				system.run(() => {
					worldUtilities.blockSlabPlace(block,itemStack,player,blockId,blockArrays.blockSlabUseOnBlocks);
					blockLocate.setType(`${itemNamespaceSplit[0]}:${removeSlab[0]}_double_slab`);
				});
			}
			if (block.typeId==item&&(blockFace=="Down"||blockFace=="Up")) {
				if (verticalHalf=="top"&&blockFace=="Down") {
					if (blockBelow.isAir) event.cancel = true;
					runSystemBlockSlab();
				}
				else if (verticalHalf=="bottom"&&blockFace=="Up") {
					if (blockAbove.isAir) event.cancel = true;
					runSystemBlockSlab();
				}
			}
			else {
				const faceCheck = {
					Down: blockBelow,
					Up: blockAbove,
					North: blockNorth,
					South: blockSouth,
					West: blockWest,
					East: blockEast
				};
				if (faceCheck[blockFace]?.typeId==item) {
					blockId = faceCheck[blockFace].typeId;
					blockLocate = faceCheck[blockFace];
					runSystemBlockSlab();
				}
			}
		}
	}
});
world.beforeEvents.playerInteractWithBlock.subscribe(({block,itemStack,player})=>{
	if (!itemStack) return;
	const id = itemStack.typeId;
	const array = defaultWorldArrays;
	if (array.addonNamespaces.some(prefix => id.startsWith(prefix))) {
		if (itemStack.hasTag("minecraft:is_shovel")) {
			const blockAbove = block.dimension.getBlock(block.above(1));
			if (array.isShovelTagUseOnBlocksToGrassPath.includes(block.typeId)) {
				if (!blockAbove.isAir) return;
				system.run(()=>{
					worldUtilities.interactToolUse(block,itemStack,player,array.isShovelTagUseOnBlocks);
					block.setType("minecraft:grass_path");
				});
			}
			if (array.isShovelTagUseOnBlocksToExtinguish.includes(block.typeId)) {
				const extinguished = block.permutation.getState("extinguished");
				if (extinguished==true) return;
				system.run(()=>{
					worldUtilities.interactToolUse(block, itemStack, player, array.isShovelTagUseOnBlocks);
					block.setPermutation(block.permutation.withState("extinguished", true));
				});
			}
		}
	}
});
world.beforeEvents.playerBreakBlock.subscribe((event) => {
	const {block,dimension,itemStack,player} = event;
	if (player.getGameMode()==GameMode.Creative) return;
	if (!itemStack) return;
	const blockId = block.typeId;
	if (blockId.startsWith("megaverse:")) {
		if (blockId.endsWith("_cake")) {
			const silkTouch = itemStack.getComponent("minecraft:enchantable")?.getEnchantment("silk_touch");
			if (!silkTouch) return;
			event.cancel = true;
			system.run(() => {
				const {x,y,z} = block.center();
				dimension.runCommand(`setblock ${x} ${y} ${z} air destroy`);
			});
		}
	}
});
world.beforeEvents.playerBreakBlock.subscribe((event) => {
	const {block,dimension,itemStack,player} = event;
	if (!itemStack) return;
	const itemId = itemStack.typeId;
	const blockId = block.typeId;
	const array = defaultWorldArrays;
	const blockNamespaceSplit = blockId.split(":");
	if (array.addonNamespaces.some(prefix=>blockId.startsWith(prefix))) {
		if (blockId.includes("_slab")&&blockId.includes("_double_")) {
			const removeDoubleSlab = blockNamespaceSplit[1].split("_double");
			const silkTouch = itemStack.getComponent("minecraft:enchantable")?.getEnchantment("silk_touch");
			if (!silkTouch) return;
			event.cancel = true;
			system.run(() => {
				const {x,y,z} = block.center();
				itemUtilities.itemToolDamage(itemStack,player);
				if (player.getGameMode()!=GameMode.Creative&&!blockArrays.blockSlabNoRequiredTool.includes(blockId)) dimension.runCommand(`loot spawn ${x} ${y} ${z} mine ${x} ${y} ${z} ${itemId}`);
				dimension.runCommand(`setblock ${x} ${y} ${z} air destroy`);
			});
		}
	}
});
/*world.afterEvents.playerPlaceBlock.subscribe(({block,dimension,player}) => {
	const id = block.typeId;
	const array = defaultWorldArrays;
	const idNamespaceSplit = id.split(":");
	if (id.startsWith("minecraft:")) {
		if (block.hasTag("pumpkin")) {
			const blockBelowA = block.dimension.getBlock(block.below(1));
			const blockBelowB = block.dimension.getBlock(block.below(2));
			if (blockBelowA.typeId=="megaverse:frost"&&blockBelowB.typeId=="megaverse:frost") {
				system.run(() => {
					blockBelowA.setType("minecraft:air");
					blockBelowB.setType("minecraft:air");
					block.setType("minecraft:air");
					dimension.spawnEntity("megaverse:frosted_slime",block.center());
				});
			}
		}
	}
});*/
world.beforeEvents.entityRemove.subscribe(({removedEntity}) => {
	const health = removedEntity.getComponent("minecraft:health")?.currentValue;
	if (health!=0) return;
	const onFire = removedEntity.getComponent("minecraft:onfire");
	if (!onFire||onFire.onFireTicksRemaining<=0) return;
	const typeFamily = removedEntity.getComponent("minecraft:type_family");
	if (!typeFamily) return;
	const amount = Math.floor(Math.random()*2)+1;
	const location = removedEntity.location;
	const dimension = removedEntity.dimension;
	const defaultFamilies = ["mob","player"];
	const undeadFamilies = ["undead"];
	const woodenFamilies = ["creaking"];
	if (woodenFamilies.some(family=>typeFamily.hasTypeFamily(family))) {
		system.run(() => {
			for (let i = 0; i < amount; i++) {
				dimension.spawnItem(new ItemStack("megaverse:wood_ash",1),location);
			}
		});
	}
	else if (undeadFamilies.some(family=>typeFamily.hasTypeFamily(family))) {
		if (Math.random()>0.25) return;
		system.run(() => {
			for (let i = 0; i < amount; i++) {
				dimension.spawnItem(new ItemStack("megaverse:ash",1),location);
			}
		});
	}
	else if (defaultFamilies.some(family=>typeFamily.hasTypeFamily(family))) {
		if (Math.random()>0.1) return;
		system.run(() => {
			for (let i = 0; i < amount; i++) {
				dimension.spawnItem(new ItemStack("megaverse:ash",1),location);
			}
		});
	}
	else return;
});
world.afterEvents.entityHitEntity.subscribe(({damagingEntity,hitEntity}) => {
	const {x,y,z} = damagingEntity.location;
	if (damagingEntity.typeId!="minecraft:player") return;
	const mainhand = damagingEntity.getComponent("minecraft:equippable").getEquipmentSlot(EquipmentSlot.Mainhand);
	if (!mainhand.hasItem()) return;
	if (mainhand.hasTag("minecraft:is_sword")||mainhand.hasTag("megaverse:otherworld_sword")) {
		if (mainhand.typeId=="minecraft:mace") return;
		if (itemArrays.weaponsAndToolsMetalTags.some(tag=>mainhand.hasTag(tag))) {
			if (itemArrays.weaponsAndToolsLongbladeTags.some(tag=>mainhand.hasTag(tag))) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.metal.longblade @a[r=16] ${x} ${y} ${z}`);
			else if (itemArrays.weaponsAndToolsBroadbladeTags.some(tag=>mainhand.hasTag(tag))) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.metal.broadblade @a[r=16] ${x} ${y} ${z}`);
			else damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.metal.shortblade @a[r=16] ${x} ${y} ${z}`);
		}
		else if (mainhand.hasTag("minecraft:stone_tier")) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.stone.tool @a[r=16] ${x} ${y} ${z}`);
		else if (mainhand.hasTag("minecraft:wooden_tier")) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.wood.sword @a[r=16] ${x} ${y} ${z}`);
		else return;
	}
	else if (mainhand.hasTag("minecraft:is_axe")) {
		if (itemArrays.weaponsAndToolsMetalTags.some(tag=>mainhand.hasTag(tag))) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.stone.tool @a[r=16] ${x} ${y} ${z}`);
		else if (mainhand.hasTag("minecraft:stone_tier")) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.stone.tool @a[r=16] ${x} ${y} ${z}`);
		else if (mainhand.hasTag("minecraft:wooden_tier")) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.wood.axe @a[r=16] ${x} ${y} ${z}`);
		else return;
	}
	else if (mainhand.hasTag("minecraft:is_tool")) {
		if (itemArrays.weaponsAndToolsMetalTags.some(tag=>mainhand.hasTag(tag))) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.metal.tool @a[r=16] ${x} ${y} ${z}`);
		else if (mainhand.hasTag("minecraft:stone_tier")) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.stone.tool @a[r=16] ${x} ${y} ${z}`);
		else if (mainhand.hasTag("minecraft:wooden_tier")) return damagingEntity.runCommand(`playsound megaverse:item.weapons_and_tools.wood.tool @a[r=16] ${x} ${y} ${z}`);
		else return;
	}
	if (mainhand.hasTag("minecraft:is_tool")) return damagingEntity.runCommand(`playsound megaverse:item.default_tool @a[r=16] ${x} ${y} ${z}`);
	else return;
});
world.beforeEvents.playerInteractWithBlock.subscribe(({block,player}) => {
	if (block.typeId!="minecraft:jukebox") return;
	const record = block.getComponent("minecraft:record_player");
	if (!record.isPlaying()) return;
	const recordType = record.getRecord();
	const musicDiscType = itemArrays.musicDiscTypePlaying[recordType.typeId];
	if (musicDiscType) {
		const {x,y,z} = block.center();
		system.run(()=>{
			player.runCommand(`stopsound @a[r=64,x=${x},y=${y},z=${z}] ${musicDiscType}`);
		});
	}
});
world.beforeEvents.playerInteractWithBlock.subscribe(({ block, blockFace, itemStack, player }) => {
	const center = block.center();
	const getDropPosition = ()=>{
		switch (blockFace) {
			case "Up": return block.above(1).center();
			case "Down": return block.below(1).center();
			case "North": return block.north(1).center();
			case "South": return block.south(1).center();
			case "West": return block.west(1).center();
			case "East": return block.east(1).center();
			default: return center;
		}
	};
	if (!itemStack&&block.typeId=="megaverse:fruiting_mulberry_leaves") {
		system.run(()=>{
			const dropPos = getDropPosition();
			block.dimension.playSound("place.dirt_with_roots",center);
			block.setType("megaverse:mulberry_leaves");
			const amount = mathUtilities.randomInteger(1, 3);
			block.dimension.spawnItem(new ItemStack("megaverse:mulberries", amount), dropPos);
		});
	}
	if (itemStack&&itemStack.typeId=="minecraft:bone_meal"&&block.typeId=="megaverse:mulberry_leaves") {
		system.run(()=>{
			itemUtilities.itemDecrementStack(itemStack,player);
			block.dimension.spawnParticle("minecraft:crop_growth_emitter",center);
			block.dimension.playSound("item.bone_meal.use",center);
			block.setType("megaverse:fruiting_mulberry_leaves");
		});
	}
});
world.beforeEvents.playerInteractWithBlock.subscribe(({block,blockFace,itemStack}) => {
	if (itemStack) return;
	const getDropPosition = ()=>{
		switch (blockFace) {
			case "Up": return block.above(1).center();
			case "Down": return block.below(1).center();
			case "North": return block.north(1).center();
			case "South": return block.south(1).center();
			case "West": return block.west(1).center();
			case "East": return block.east(1).center();
			default: return center;
		}
	};
	if (block.typeId=="megaverse:truffled_dirt_cluster") {
		system.run(()=>{
			const dropPos = getDropPosition();
			block.dimension.playSound("place.dirt_with_roots",block.center());
			block.setType("minecraft:dirt_with_roots");
			const amount = mathUtilities.randomInteger(1,4);
			block.dimension.spawnItem(new ItemStack("megaverse:truffle",amount),dropPos);
		});
	}
});
world.beforeEvents.playerInteractWithBlock.subscribe(({block,itemStack,player}) => {
	const rule = blockArrays.blockChiseledTypes[block.typeId];
	const array = defaultWorldArrays;
	if (!rule) return;
	if (!itemStack) return;
	if (itemStack.hasTag("megaverse:is_chisel")) {
		system.run(()=>{
			player.playSound("scrape",{location:block.center()});
			if (rule.blockTurnsWithBlockFace) return block.setPermutation(BlockPermutation.resolve(rule.blockTurnsInto,{[rule.blockTurnsWithBlockFace]:rule.blockIntoBlockFaceState(block,rule.blockTurnsWithBlockFace)}));
			else if (rule.blockTurnsInto) block.setType(rule.blockTurnsInto);
			else block.setType(rule);
		});
	}
	else return;
});
world.beforeEvents.playerInteractWithBlock.subscribe(({block,itemStack,player}) => {
	const rule = blockArrays.blockWoodStrippedTypes[block.typeId];
	const array = defaultWorldArrays;
	if (!rule) return;
	if (itemStack.hasTag("minecraft:is_axe")) {
		system.run(()=>{
			worldUtilities.interactToolUse(block,itemStack,player,array.isAxeTagInteractBlocks);
			if (rule.blockTurnsWithBlockFace) return block.setPermutation(BlockPermutation.resolve(rule.blockTurnsInto,{[rule.blockTurnsWithBlockFace]:rule.blockIntoBlockFaceState(block,rule.blockTurnsWithBlockFace)}));
			else block.setType(rule.blockTurnsInto);
		});
	}
});

world.afterEvents.playerInteractWithBlock.subscribe(({block,itemStack,player}) => {
	if (!itemStack) return;
	const id = itemStack.typeId;
	const array = defaultWorldArrays;
	if (array.addonNamespaces.some(prefix=>id.startsWith(prefix))) {
		if (itemStack.hasTag("minecraft:is_axe")) return worldUtilities.interactToolUse(block,itemStack,player,array.isAxeTagInteractBlocks);
		if (itemStack.hasTag("minecraft:is_hoe")) return worldUtilities.interactToolUse(block,itemStack,player,array.isHoeTagInteractBlocks);
		if (itemStack.hasTag("minecraft:is_shovel")) return worldUtilities.interactToolUse(block,itemStack,player,array.isShovelTagInteractBlocks);
	}
});
world.afterEvents.dataDrivenEntityTrigger.subscribe(({entity,eventId}) => {
	if (entity.typeId.includes("megaverse:falling_frost")&&eventId=="minecraft:falling_block_on_ground") {
		const convert = entity.typeId.split(":falling_");
		entity.dimension.spawnParticle(`${convert[0]}${convert[1]}`,{x:entity.location.x,y:entity.location.y,z:entity.location.z});
		if (entity.typeId.includes("gravel")) entity.dimension.playSound("break.suspicious_gravel",{x:entity.location.x,y:entity.location.y,z:entity.location.z});
		else entity.dimension.playSound("break.suspicious_sand",{x:entity.location.x,y:entity.location.y,z:entity.location.z});
	}
});
/*world.beforeEvents.playerInteractWithEntity.subscribe((event) => {
	const {cancel,itemStack,player,target} = event;
	const tameable = event.target.getComponent("tameable");
    if (target.typeId=="megaverse:dracon"||itemStack.hasTag("minecraft:is_meat")) {
        system.run(() => {
            tameable.tame(event.player);
        });
    }
});*/
world.beforeEvents.itemUse.subscribe((event) => {
    const {itemStack,source:player} = event;
    if (player.getGameMode()==GameMode.Creative) return;
    const arrowTypes = itemArrays.bowTypesList.includes(itemStack.typeId);
	if (!arrowTypes) return;
	const rule = itemArrays.bowTypes[itemStack.typeId];
	if (!rule) return;
    const offhand = player.getComponent("minecraft:equippable").getEquipment(EquipmentSlot.Offhand);
    const inventory = player.getComponent("minecraft:inventory").container;
    let hasArrows = false;
    if (offhand&&rule.ammunition.includes(offhand.typeId)&&offhand.amount>0) {
        hasArrows = true;
    }
    if (!hasArrows) {
        for (let i = 0; i < inventory.size; i++) {
            const item = inventory.getItem(i);
            if (item&&rule.ammunition.includes(item.typeId)&&item.amount>0) {
                hasArrows = true;
                break;
            }
        }
    }
    if (!hasArrows) event.cancel = true;
});