package ru.dbotthepony.mc.otm.capability.matter

import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.core.util.readBinaryJsonWithCodec
import ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
import ru.dbotthepony.mc.otm.data.UUIDCodec
import java.util.*

data class PatternState(
	val id: UUID,
	val item: Item,
	val researchPercent: Double,
) {
	fun matchId(other: PatternState): Boolean {
		return other.id == id
	}

	fun stack(count: Int = 1): ItemStack {
		return ItemStack(item, count)
	}

	fun write(buff: FriendlyByteBuf) {
		buff.writeBinaryJsonWithCodec(CODEC, this)
	}

	fun serializeNBT(): CompoundTag {
		return CODEC.encode(this, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).get()
			.map({ it as CompoundTag }, { throw RuntimeException("Failed to serialize PatternState: ${it.message()}") })
	}

	companion object {
		fun deserializeNBT(tag: Tag?): PatternState? {
			tag ?: return null
			return CODEC.decode(NbtOps.INSTANCE, tag).result().map { it.first }.orElse(null)
		}

		fun read(buff: FriendlyByteBuf): PatternState {
			return buff.readBinaryJsonWithCodec(CODEC)
		}

		val CODEC: Codec<PatternState> by lazy {
			RecordCodecBuilder.create {
				it.group(
					UUIDCodec.fieldOf("id").forGetter(PatternState::id),
					ForgeRegistries.ITEMS.codec.fieldOf("item").forGetter(PatternState::item),
					Codec.doubleRange(0.0, 1.0).fieldOf("researchPercent").forGetter(PatternState::researchPercent)
				).apply(it, ::PatternState)
			}
		}
	}
}
