package ru.dbotthepony.mc.otm.recipe

import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.set

fun stackFromJson(obj: JsonElement, field: String = "<unknown>"): ItemStack {
	if (obj is JsonPrimitive) {
		check(obj.isString) { "Field $field is supposed to be an Item, but it is malformed (not a string and not an object)" }
		val item = ForgeRegistries.ITEMS.getValue(ResourceLocation(obj.asString)) ?: return ItemStack.EMPTY

		if (item === Items.AIR) {
			return ItemStack.EMPTY
		}

		return ItemStack(item, 1)
	}

	if (obj is JsonObject) {
		val name = obj["name"] as? JsonPrimitive ?: throw IllegalStateException("Invalid name of $field")
		check(name.isString) { "Invalid name of $field (supposed to be a string)" }
		val item = ForgeRegistries.ITEMS.getValue(ResourceLocation(name.asString)) ?: return ItemStack.EMPTY

		val count = (obj["count"] as? JsonPrimitive)?.let {
			try {
				return@let it.asInt
			} catch(err: Throwable) {
				throw IllegalStateException("Invalid format of count of $field (supposed to be a number)", err)
			}
		} ?: 1

		check(count > 0) { "Field count of $field does not make any sense" }

		return ItemStack(item, count)
	}

	throw IllegalStateException("Invalid or missing $field")
}

fun stackToJson(stack: ItemStack, field: String = "<unknown>"): JsonElement {
	check(stack.count > 0) { "ItemStack $field is empty" }

	if (stack.count == 1) {
		return JsonPrimitive(stack.item.registryName!!.toString())
	}

	return JsonObject().also {
		it["name"] = JsonPrimitive(stack.item.registryName!!.toString())
		it["count"] = JsonPrimitive(stack.count)
	}
}
