package ru.dbotthepony.mc.otm.menu.tech

import mezz.jei.api.recipe.RecipeType
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.inventory.MenuType
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
import ru.dbotthepony.mc.otm.compat.jei.PlatePressRecipeCategory
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.menu.OutputSlot
import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
import ru.dbotthepony.mc.otm.registry.game.MMenus
import java.util.function.Supplier

class PlatePressMenu(
	type: MenuType<*>,
	containerID: Int,
	inventory: Inventory,
	tile: PlatePressBlockEntity? = null,
	isTwin: Boolean
) : AbstractProcessingMachineMenu(type, containerID, inventory, tile) {
	val inputSlots = makeSlots(tile?.inputContainer ?: SimpleContainer(if (isTwin) 2 else 1), ::MatterySlot)
	val outputSlots = makeSlots(tile?.outputContainer ?: SimpleContainer(if (isTwin) 2 else 1)) { a, b -> OutputSlot(a, b) { tile?.experience?.popExperience(player as ServerPlayer) } }
	val gauges = immutableList(if (isTwin) 2 else 1) { ProgressGaugeWidget(this, tile?.jobEventLoops?.get(it)) }

	override val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true)
	override val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig, allowPull = true)
	override val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget)

	override val balanceInputs = if (isTwin) BooleanInputWithFeedback(this) else null
	override val upgrades = makeUpgradeSlots(if (isTwin) 4 else 3, tile?.upgrades)
	override val experience = TakeExperienceWidget(this, tile?.experience)

	override val processingTuples: List<ProcessingTuple> = immutableList(if (isTwin) 2 else 1) {
		ProcessingTuple(inputSlots[it], outputSlots[it], gauges[it])
	}

	override val recipeTypes: Supplier<List<RecipeType<*>>>
		get() = Supplier { listOf(PlatePressRecipeCategory.recipeType) }

	init {
		if (tile != null) balanceInputs?.with(tile::balanceInputs)
		addStorageSlot(inputSlots)
		addStorageSlot(outputSlots)
	}

	companion object {
		fun single(containerID: Int, inventory: Inventory, tile: PlatePressBlockEntity? = null): PlatePressMenu {
			return PlatePressMenu(MMenus.PLATE_PRESS, containerID, inventory, tile, false)
		}

		fun twin(containerID: Int, inventory: Inventory, tile: PlatePressBlockEntity? = null): PlatePressMenu {
			return PlatePressMenu(MMenus.TWIN_PLATE_PRESS, containerID, inventory, tile, true)
		}
	}
}
