import { ItemStack, EquipmentSlot, EnchantmentType, EntityComponentTypes, ItemLockMode } from "@minecraft/server";
import * as utils from "./utils";
import * as wallet from "./wallet";
import { showApp as color_customizer } from "./apps/color_customizer";


export async function countItemInInventory(player, itemTypeId)
{
	const inventory = player.getComponent("minecraft:inventory").container;
	let itemCount = 0;
	for (let i = 0; i < inventory.size; i++) {
		let item = inventory.getItem(i);
		if (item !== undefined && item.typeId === itemTypeId)
			itemCount += item.amount;
	}
	return itemCount;
}

export function isHoldingPhone(player){
	const equipment = player.getComponent("equippable");
	let itemInHand = equipment.getEquipment(EquipmentSlot.Mainhand);
	if(itemInHand === undefined)
		return false;
	return (itemInHand.typeId.endsWith("_smartphone") || itemInHand.typeId.endsWith("_smartphone_hud"));
}
export function isHoldingOpenPhone(player){
	const equipment = player.getComponent("equippable");
	let itemInHand = equipment.getEquipment(EquipmentSlot.Mainhand);
	if(itemInHand === undefined)
		return false;
	return (itemInHand.typeId.endsWith("_smartphone_hud"));
}
export function isItemInHand(player, itemTypeId){
	let itemInHand = getItemInHand(player);
	if(itemInHand === undefined)
		return false;
	if (itemInHand.typeId === itemTypeId)
		return true;
	return false;
}

export function replaceChargedPhone(player) {
	const inventory = player.getComponent("inventory").container;
	for (let i = 0; i < inventory.size; i++) {
		const slot = inventory.getSlot(i);
		const item = slot.getItem();
		if (item === undefined || !item.typeId.endsWith("_smartphone_charged"))
			continue;

		const newPhone = new ItemStack(item.typeId.replace("_charged", ""), 1);
		slot.setItem(newPhone);
		
		player.onScreenDisplay.setActionBar("Smartphone fully charged!");
		player.playSound("goe_spa:charged");
		player.dimension.spawnParticle("goe_spa:charged", player.location);
	}
}

export function getItemInHand(player){
	return player.getComponent("inventory").container.getItem(player.selectedSlotIndex);
}

export async function lockHeldItem(player)
{
	const inventory = player.getComponent("inventory").container;
	let phone = inventory.getItem(player.selectedSlotIndex);
	let newPhone = new ItemStack(phone.typeId);
	newPhone.lockMode = ItemLockMode.slot;
	newPhone.getComponent("durability").damage = phone.getComponent("durability").damage;
	inventory.setItem(player.selectedSlotIndex, newPhone);
}
export async function unlockHeldItem(player)
{
	const inventory = player.getComponent("inventory").container;
	let phone = inventory.getItem(player.selectedSlotIndex);
	let newPhone = new ItemStack(phone.typeId);
	newPhone.lockMode = ItemLockMode.none;
	newPhone.getComponent("durability").damage = phone.getComponent("durability").damage;
	inventory.setItem(player.selectedSlotIndex, newPhone);
}

export function replacePhoneIfUIClosed(player, response){
	
	if (response === undefined || response.canceled){
		utils.runPlayerCommand(player, "camera @s clear");
		const inventory = player.getComponent("inventory").container;
		const phoneSlot = player.getDynamicProperty("goe_spa_phone_slot");
		let phoneHud = inventory.getItem(phoneSlot);
		if (phoneHud === undefined)
			return;
		let phoneItem = new ItemStack(phoneHud.typeId.replace("_hud", ""));
		phoneItem.getComponent("durability").damage = phoneHud.getComponent("durability").damage;
		const playerInventory = player.getComponent("inventory").container;
		playerInventory.setItem(phoneSlot, phoneItem);
		player.playSound("goe_spa:lock_phone");
	}
}

export async function setPhoneHud(player)
{
	const inventory = player.getComponent("inventory").container;
	const phoneSlot = player.getDynamicProperty("goe_spa_phone_slot");
	let phoneItem = inventory.getItem(phoneSlot);
	if (phoneItem.typeId.endsWith("_smartphone_hud"))
		return;
	let phoneHudItem = new ItemStack(phoneItem.typeId+"_hud");
	phoneHudItem.getComponent("durability").damage = phoneItem.getComponent("durability").damage;
	inventory.setItem(phoneSlot, phoneHudItem);

}

export async function drainPhone(player, amount)
{
	const inventory = player.getComponent("inventory").container;
	const phoneSlot = player.getDynamicProperty("goe_spa_phone_slot");
	let phoneItem = inventory.getItem(phoneSlot);
	if (phoneItem === undefined)
		return;
	let dmg = phoneItem.getComponent("durability").damage + amount;
	let maxDamage = phoneItem.getComponent("durability").maxDurability;
	if (dmg >= maxDamage)
		dmg = maxDamage-1;
	let drainedPhoneItem = new ItemStack(phoneItem.typeId);
	drainedPhoneItem.lockMode = phoneItem.lockMode;
	drainedPhoneItem.getComponent("durability").damage = dmg;
	inventory.setItem(phoneSlot, drainedPhoneItem);
}
export async function setSatelliteaHud(player)
{
	utils.runPlayerCommand(player, "replaceitem entity @s slot.armor.head 0 goe_spa:satellite_hud");
}

export async function storeArmorInMemory(player)
{
		if (player == undefined)
		{
			console.warn("storeArmorInMemory got undefined player");
			return;
		}
		
		const equipment = await player.getComponent("equippable");
		await storeArmorItemInMemory(player, equipment, EquipmentSlot.Head);
		await storeArmorItemInMemory(player, equipment, EquipmentSlot.Chest);
		await storeArmorItemInMemory(player, equipment, EquipmentSlot.Legs);
		await storeArmorItemInMemory(player, equipment, EquipmentSlot.Feet);
		await storeArmorItemInMemory(player, equipment, EquipmentSlot.Mainhand);
		await storeArmorItemInMemory(player, equipment, EquipmentSlot.Offhand);
		await player.setDynamicProperty(`goe_spa_stored_armor`, true);
}

async function storeArmorItemInMemory(player, equipment, slotName)
{
	let item = equipment.getEquipment(slotName);
	if (item === undefined)
		return;
	player.setDynamicProperty(`goe_spa_${slotName}_name`, item.typeId);
	player.setDynamicProperty(`goe_spa_${slotName}_dmg`, item.getComponent("durability").damage);
	equipment.setEquipment(slotName, undefined);

	// Save enchantments
	saveEnchantments(player, item, slotName);
}

async function saveEnchantments(player, item, slotName) {	
	let enchantmentsString = "";
	const enchantableComponent = item.getComponent("minecraft:enchantable");
	if (!enchantableComponent)
		return;

    const enchantments = enchantableComponent.getEnchantments();
	for (const enchantment of enchantments) {
		enchantmentsString += enchantment.type.id + " " + enchantment.level + " ";
	}

	player.setDynamicProperty(`goe_spa_${slotName}_enchantments`, enchantmentsString);
}

export async function restoreArmorFromMemory(player)
{
		if (player == undefined)
		{
			console.warn("storeArmorInMemory got undefined player");
			return;
		}
		
		const equipment = await player.getComponent("equippable");
		await restoreArmorItemFromMemory(player, equipment, EquipmentSlot.Head);
		await restoreArmorItemFromMemory(player, equipment, EquipmentSlot.Chest);
		await restoreArmorItemFromMemory(player, equipment, EquipmentSlot.Legs);
		await restoreArmorItemFromMemory(player, equipment, EquipmentSlot.Feet);
		await restoreArmorItemFromMemory(player, equipment, EquipmentSlot.Mainhand);
		await restoreArmorItemFromMemory(player, equipment, EquipmentSlot.Offhand);
		await player.setDynamicProperty(`goe_spa_stored_armor`);
}
async function restoreArmorItemFromMemory(player, equipment, slotName)
{
	let itemName = await player.getDynamicProperty(`goe_spa_${slotName}_name`);
	if (itemName === undefined)
	{
		equipment.setEquipment(slotName, undefined);
		player.setDynamicProperty(`goe_spa_${slotName}_name`, undefined);
		player.setDynamicProperty(`goe_spa_${slotName}_dmg`, undefined);
		return;
	}
	let dmg = await player.getDynamicProperty(`goe_spa_${slotName}_dmg`);
	dmg = dmg ? dmg : 0;
	
	let newItem = new ItemStack(itemName);
	newItem.getComponent("durability").damage = dmg;
	await loadEnchantments(player, newItem, slotName);
	equipment.setEquipment(slotName, newItem);
	player.setDynamicProperty(`goe_spa_${slotName}_name`, undefined);
	player.setDynamicProperty(`goe_spa_${slotName}_dmg`, undefined);
}

async function loadEnchantments(player, item, slotName) {	
	const enchantmentsString = player.getDynamicProperty(`goe_spa_${slotName}_enchantments`);
	if (enchantmentsString === undefined || enchantmentsString === "")
		return;

	const enchantmentParts = enchantmentsString.split(" ");
	const enchantableComponent = item.getComponent("minecraft:enchantable");
	if (enchantableComponent === undefined)
		return;

	for (let i = 0; i < enchantmentParts.length; i += 2) {
		if (enchantmentParts[i] === "")
			continue;

		enchantableComponent.addEnchantment({
			type: new EnchantmentType(enchantmentParts[i]),
			level: parseInt(enchantmentParts[i + 1])
		});
	}
	
	player.setDynamicProperty(`goe_spa_${slotName}_enchantments`, undefined);
}

export async function spawnPhoneItemAfterDeath(phoneHudItem)
{
	let phoneItemComponent = phoneHudItem.getComponent(EntityComponentTypes.Item);
	let phoneName = phoneItemComponent.itemStack.typeId.replace("_hud", "");
	let phoneItem = new ItemStack(phoneName);
	//let damage = phoneItemComponent.itemStack.getComponent("durability").damage;
	//utils.debug("damage = "+damage);
	phoneItem.getComponent("durability").damage = 600;
	await phoneHudItem.dimension.spawnItem(phoneItem, phoneHudItem.location);
	await phoneHudItem.remove();
}

export async function changePhoneColor(player, phoneTypeId, cost) {
	try {
		const inventory = player.getComponent("inventory").container;
		const phoneSlot = player.getDynamicProperty("goe_spa_phone_slot");
		let phoneItem = inventory.getItem(phoneSlot);
		if (phoneItem === undefined)
			return;
		if (phoneItem.typeId === phoneTypeId){
			player.playSound("goe_spa:reject");
			color_customizer(player);
			return;
		}
		let dmg = phoneItem.getComponent("durability").damage;
		let maxDamage = phoneItem.getComponent("durability").maxDurability;
		if (dmg >= maxDamage)
			dmg = maxDamage-1;
		let newColorPhone = new ItemStack(phoneTypeId);
		newColorPhone.getComponent("durability").damage = dmg;
		inventory.setItem(phoneSlot, newColorPhone);
		wallet.charge(player, cost);
		player.playSound("goe_spa:purchase", { volume: 0.3 });
		player.playSound("goe_spa:spray");
		player.dimension.spawnParticle("goe_spa:bought", player.location);
		color_customizer(player);
	} catch {
		utils.debug("Trasantion failed. Please try again.");
	}
}

export async function removeItemInHand(player) {
	const inventory = player.getComponent("inventory").container;
	inventory.setItem(player.selectedSlotIndex, undefined);
}