package ru.dbotthepony.mc.otm.capability.fluid

import net.minecraft.core.HolderLookup
import net.minecraft.core.component.DataComponents
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.component.CustomData
import net.neoforged.neoforge.common.util.INBTSerializable
import net.neoforged.neoforge.fluids.FluidStack
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.Registries
import ru.dbotthepony.mc.otm.core.nbt.set
import java.util.function.IntSupplier

/**
 * Fluid handler for blocks
 */
open class BlockMatteryFluidHandler(private val _capacity: IntSupplier, field: Delegate<FluidStack>) : AbstractMatteryFluidHandler(), INBTSerializable<Tag?> {
	override var fluid by field

	override val capacity: Int
		get() = _capacity.asInt

	override fun serializeNBT(registry: HolderLookup.Provider): Tag {
		return fluid.saveOptional(registry)
	}

	override fun deserializeNBT(registry: HolderLookup.Provider, nbt: Tag?) {
		if (nbt !is CompoundTag)
			fluid = FluidStack.EMPTY
		else
			fluid = FluidStack.parseOptional(registry, nbt)
	}

	/**
	 * Fluid handler for items representing block with [BlockMatteryFluidHandler]
	 */
	open class Item(itemStack: ItemStack, capacity: IntSupplier, private val nbtName: String, private val blockEntityID: ResourceLocation) : ItemMatteryFluidHandler(itemStack, capacity) {
		override var fluid: FluidStack
			get() {
				val custom = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY)
				val sub = custom.unsafe[nbtName] as? CompoundTag ?: return FluidStack.EMPTY
				return FluidStack.parseOptional(Registries, sub)
			}
			set(value) {
				val data = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY)

				itemStack[DataComponents.BLOCK_ENTITY_DATA] = CustomData.of(data.copyTag().also {
					it[nbtName] = value.saveOptional(Registries)

					// workaround for minecraft requiring block entity IDs inside blockitems
					// but why? it is not used, like, anywhere.
					if ("id" !in it) {
						it["id"] = blockEntityID.toString()
					}
				})
			}
	}
}
