import { ItemStack, world } from '@minecraft/server';
import { decrementItemInInventory } from '../util/utils';

export class McfDishwasher {
	static getWashData(entity) {
		return {
			soapProgress: entity.getDynamicProperty("mr:soap_progress") ?? 0,
			soapValue: entity.getDynamicProperty("mr:soap_value") ?? 0,
			soapTick: entity.getDynamicProperty("mr:soap_tick") ?? 0,
			bubbles: entity.getDynamicProperty("mr:bubbles") ?? 0
		};
	}
	static setWashData(entity, data) {
		entity.setDynamicProperty("mr:soap_progress", data.soapProgress);
		entity.setDynamicProperty("mr:soap_value", data.soapValue);
		entity.setDynamicProperty("mr:soap_tick", data.soapTick);
		entity.setDynamicProperty("mr:bubbles", data.bubbles);
	}
	static validateToolSlots(inventory, entity) {
		const toolSlots = [
			{ slot: 1, tag: "minecraft:is_sword" },
			{ slot: 2, tag: "minecraft:is_shovel" },
			{ slot: 3, tag: "minecraft:is_pickaxe" },
			{ slot: 4, tag: "minecraft:is_axe" },
			{ slot: 5, tag: "minecraft:is_hoe" },
			{ slot: 6, tag: "minecraft:is_trident" }
		];
		for (const { slot, tag } of toolSlots) {
			const item = inventory.getItem(slot);
			if (item && !item.hasTag(tag)) {
				entity.dimension.spawnItem(item, entity.location);
				inventory.setItem(slot, undefined);
			}
		}
	}
	static needsWashing(tools) {
		return tools.some(item => {
			if (!item) return false;
			const durability = item.getComponent("durability");
			return durability && durability.damage > 0;
		});
	}
	static getTools(inventory) {
		return [
			inventory.getItem(1),
			inventory.getItem(2),
			inventory.getItem(3),
			inventory.getItem(4),
			inventory.getItem(5),
			inventory.getItem(6)
		];
	}
	static setupSoapTimer(inventory, soap, washData) {
		if (soap.typeId === "mr:soap_water") {
			inventory.setItem(7, new ItemStack("mr:timer", 64));
			washData.soapValue = 30;
		} else if (soap.typeId === "mr:super_soap_water") {
			inventory.setItem(8, new ItemStack("mr:timer", 64));
			washData.soapValue = 10;
		}
		washData.soapProgress = 2500;
	}
	static updateTimers(inventory, washData) {
		const timerSlot = (washData.soapValue === 30 ? 7 : 8);
		const valueSoap = Math.max(1, Math.ceil((washData.soapProgress / 2500) * 64));
		const valueBubbles = Math.max(1, Math.ceil((washData.soapTick / washData.soapValue) * 64));
		inventory.setItem(timerSlot, new ItemStack("mr:timer", valueSoap));
		inventory.setItem(9, new ItemStack("mr:timer", valueBubbles));
	}
	static repairTools(tools, inventory) {
		tools.forEach((item, i) => {
			if (!item) return;
			const durability = item.getComponent("durability");
			if (durability?.damage > 0) {
				durability.damage = Math.min(durability.damage - 1, durability.maxDurability);
				inventory.setItem(i + 1, item);
			}
		});
	}
	static stopWashing(entity, inventory, washData) {
		washData.bubbles = 0;
		inventory.setItem(9, new ItemStack("mr:timer", 1));
		this.setWashData(entity, washData);
		entity.triggerEvent("mr:stop");
	}
	static resetSoapValues(entity, inventory, washData) {
		washData.bubbles = 0;
		washData.soapTick = 0;
		washData.soapValue = 0;
		inventory.setItem(7, new ItemStack("mr:timer", 1));
		inventory.setItem(8, new ItemStack("mr:timer", 1));
		inventory.setItem(9, new ItemStack("mr:timer", 1));
		this.setWashData(entity, washData);
		entity.triggerEvent("mr:stop");
	}
	static handleCheckEvent(entity, inventory, washData) {
		this.validateToolSlots(inventory, entity);
		const soap = inventory.getItem(0);
		const tools = this.getTools(inventory);
		const needsWash = this.needsWashing(tools);
		if (soap?.hasTag("mc:is_soap") && washData.soapProgress <= 0 && needsWash) {
			this.setupSoapTimer(inventory, soap, washData);
			decrementItemInInventory(entity, 0, { convertTo: new ItemStack("minecraft:bucket", 1) });
		}
		if (washData.soapProgress > 0 && needsWash) {
			this.setWashData(entity, washData);
			entity.triggerEvent("mr:start");
			return;
		}
		this.setWashData(entity, washData);
	}
	static handleUpdateTimerEvent(entity, inventory, washData) {
		this.validateToolSlots(inventory, entity);
		const tools = this.getTools(inventory);
		const needsWash = this.needsWashing(tools);
		if (!needsWash) return this.stopWashing(entity, inventory, washData);
		if (washData.soapProgress <= 0) return this.resetSoapValues(entity, inventory, washData);
		washData.soapProgress--;
		washData.soapTick++;
		if (washData.soapTick >= washData.soapValue) {
			washData.soapTick = 0;
			this.repairTools(tools, inventory);
		}
		this.updateTimers(inventory, washData);
		this.setWashData(entity, washData);
	}
	static registerEvent() {
		world.afterEvents.dataDrivenEntityTrigger.subscribe(({ entity, eventId }) => {
			if (!entity?.isValid) return;
			const inventory = entity.getComponent("inventory").container;
			const washData = this.getWashData(entity);
			if (eventId === "mr:check") this.handleCheckEvent(entity, inventory, washData);
			if (eventId === "mr:update_timer") this.handleUpdateTimerEvent(entity, inventory, washData);
		}, {
			entityTypes: ["mr:dishwasher"],
			eventTypes: ["mr:check", "mr:update_timer"]
		})
	}
}