package ru.dbotthepony.mc.otm.recipe

import com.google.gson.JsonObject
import net.minecraft.core.NonNullList
import net.minecraft.core.RegistryAccess
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.CraftingBookCategory
import net.minecraft.world.item.crafting.CraftingRecipe
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.item.crafting.ShapedRecipe
import net.minecraft.world.level.Level
import net.minecraftforge.common.crafting.IShapedRecipe
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.core.filterNotNull

class EnergyContainerRecipe(val parent: ShapedRecipe) : CraftingRecipe, IShapedRecipe<CraftingContainer> by parent {
	override fun canCraftInDimensions(p_43999_: Int, p_44000_: Int): Boolean {
		return parent.canCraftInDimensions(p_43999_, p_44000_)
	}

	override fun getResultItem(p_267052_: RegistryAccess): ItemStack {
		return parent.getResultItem(p_267052_)
	}

	override fun getId(): ResourceLocation {
		return parent.id
	}

	override fun category(): CraftingBookCategory {
		return parent.category()
	}

	override fun getRemainingItems(p_44004_: CraftingContainer): NonNullList<ItemStack> {
		return parent.getRemainingItems(p_44004_)
	}

	override fun getIngredients(): NonNullList<Ingredient> {
		return parent.ingredients
	}

	override fun isSpecial(): Boolean {
		return parent.isSpecial
	}

	override fun showNotification(): Boolean {
		return parent.showNotification()
	}

	override fun getGroup(): String {
		return parent.group
	}

	override fun getToastSymbol(): ItemStack {
		return parent.toastSymbol
	}

	override fun isIncomplete(): Boolean {
		return parent.isIncomplete
	}

	override fun getType(): RecipeType<*> {
		return parent.type
	}

	override fun assemble(container: CraftingContainer, registryAccess: RegistryAccess): ItemStack {
		val itemStack = parent.assemble(container, registryAccess)

		val battery = container.stream()
			.filter { !it.isEmpty }
			.map { it.matteryEnergy }
			.filterNotNull()
			.findAny().orElse(null)

		if (battery != null) {
			itemStack.matteryEnergy?.batteryLevel = battery.batteryLevel
		}

		if (itemStack.isEnchantable) {
			for (it in container.iterator()) {
				if (!it.isEmpty && it.isEnchanted) {
					for ((key, value) in it.allEnchantments) {
						itemStack.enchant(key, value)
					}
				}
			}
		}

		return itemStack
	}

	override fun matches(container: CraftingContainer, level: Level): Boolean {
		return parent.matches(container, level) && !container.stream().anyMatch { it.isDamaged }
	}

	override fun getSerializer(): RecipeSerializer<EnergyContainerRecipe> {
		return Companion
	}

	companion object : RecipeSerializer<EnergyContainerRecipe> {
		override fun fromJson(id: ResourceLocation, data: JsonObject): EnergyContainerRecipe {
			return EnergyContainerRecipe(ShapedRecipe.Serializer.SHAPED_RECIPE.fromJson(id, data))
		}

		override fun fromNetwork(id: ResourceLocation, data: FriendlyByteBuf): EnergyContainerRecipe? {
			return ShapedRecipe.Serializer.SHAPED_RECIPE.fromNetwork(id, data)?.let(::EnergyContainerRecipe)
		}

		override fun toNetwork(buff: FriendlyByteBuf, value: EnergyContainerRecipe) {
			ShapedRecipe.Serializer.SHAPED_RECIPE.toNetwork(buff, value.parent)
		}
	}
}
