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

export class McfOven {
	static getOvenData(entity) {
		return {
			progress: entity.getDynamicProperty("mr:oven_progress") ?? 0,
			total: entity.getDynamicProperty("mr:oven_total") ?? 0,
			lastSlotCount: entity.getDynamicProperty("mr:oven_last_slot_count") ?? 0
		};
	}
	static setOvenData(entity, data) {
		entity.setDynamicProperty("mr:oven_progress", data.progress);
		entity.setDynamicProperty("mr:oven_total", data.total);
		entity.setDynamicProperty("mr:oven_last_slot_count", data.lastSlotCount);
	}
	static calculateCookingTime(activeSlots) {
		return 100 + (50 * (activeSlots - 1));
	}
	static getValidSlots(inventory) {
		const valid = [];
		for (let i = 0; i < 4; i++) {
			const input = inventory.getItem(i);
			if (!input || !COOKING_RECIPES[input.typeId]) continue;
			const resultId = COOKING_RECIPES[input.typeId];
			const output = inventory.getItem(i + 4);
			if (!output || (output.typeId === resultId && output.amount < output.maxAmount)) valid.push(i);
		}
		return valid;
	}
	static updateVisuals(inventory, validSlots, progress, total) {
		for (let i = 0; i < 4; i++) {
			const visual = validSlots.includes(i) ? Math.max(1, Math.ceil((progress / total) * 64)) : 1;
			inventory.setItem(i + 8, new ItemStack("mr:timer", visual));
		}
	}
	static processCompletedCooking(entity, inventory, validSlots) {
		for (const i of validSlots) {
			const input = inventory.getItem(i);
			if (!input) continue;
			const resultId = COOKING_RECIPES[input.typeId];
			const resultItem = new ItemStack(resultId, 1);
			const outputSlot = i + 4;
			if (addItemInInventory(inventory, outputSlot, resultItem)) decrementItemInInventory(entity, i);
		}
	}
	static handleCheckEvent(entity, inventory, ovenData) {
		const validSlots = this.getValidSlots(inventory);
		const slotCount = validSlots.length;
		if (slotCount > 0) {
			if (slotCount !== ovenData.lastSlotCount) {
				ovenData.total = this.calculateCookingTime(slotCount);
				ovenData.lastSlotCount = slotCount;
			}
			ovenData.progress = 0;
			this.setOvenData(entity, ovenData);
			this.updateVisuals(inventory, validSlots, 0, ovenData.total);
			entity.triggerEvent("mr:start");
		}
	}
	static handleUpdateTimerEvent(entity, inventory, ovenData) {
		const validSlots = this.getValidSlots(inventory);
		const slotCount = validSlots.length;
		if (slotCount === 0) {
			if (ovenData.total > 0) {
				ovenData.progress = 0;
				ovenData.total = 0;
				ovenData.lastSlotCount = 0;
				this.setOvenData(entity, ovenData);
				this.updateVisuals(inventory, [], 0, 1);
				entity.triggerEvent("mr:stop");
			}
			return;
		}
		if (slotCount !== ovenData.lastSlotCount) {
			ovenData.total = this.calculateCookingTime(slotCount);
			ovenData.lastSlotCount = slotCount;
		}
		ovenData.progress++;
		if (ovenData.progress >= ovenData.total) {
			this.processCompletedCooking(entity, inventory, validSlots);
			ovenData.progress = 0;
		}
		this.updateVisuals(inventory, validSlots, ovenData.progress, ovenData.total);
		this.setOvenData(entity, ovenData);
	}
	static registerEvent() {
		world.afterEvents.dataDrivenEntityTrigger.subscribe(({ entity, eventId }) => {
			if (!entity?.isValid) return;
			const inventory = entity.getComponent("inventory").container;
			const ovenData = this.getOvenData(entity);
			if (eventId === "mr:check") this.handleCheckEvent(entity, inventory, ovenData);
			if (eventId === "mr:update_timer") this.handleUpdateTimerEvent(entity, inventory, ovenData);
		}, {
			entityTypes: ["mr:oven"],
			eventTypes: ["mr:check", "mr:update_timer"]
		})
	}
}