package ru.dbotthepony.mc.otm.data

import com.mojang.datafixers.util.Pair
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import com.mojang.serialization.DynamicOps
import net.minecraft.nbt.NbtOps
import java.util.UUID
import java.util.stream.LongStream

// because UUIDUtil codec is in unexpected place
// and can't work with both strings, array of longs and array of ints
object UUIDCodec : Codec<UUID> {
	override fun <T : Any> encode(input: UUID, ops: DynamicOps<T>, prefix: T): DataResult<T> {
		if (ops === NbtOps.INSTANCE) {
			return DataResult.success((ops as DynamicOps<T>).createLongList(LongStream.of(input.mostSignificantBits, input.leastSignificantBits)))
		}

		return DataResult.success(ops.createString(input.toString()))
	}

	override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<UUID, T>> {
		return ops.getLongStream(input).flatMap {
			val l = it.limit(4).toArray()

			if (l.size == 4) {
				// 4 int
				DataResult.success(Pair(UUID((l[0] shl 32) or l[1], (l[2] shl 32) or l[3]), ops.empty()))
			} else if (l.size == 2) {
				DataResult.success(Pair(UUID(l[0], l[1]), ops.empty()))
			} else {
				DataResult.error { "Can't construct UUID from ${l.size} elements" }
			}
		}.get().map(
			{
				DataResult.success(it)
			},
			{ e0 ->
				ops.getStringValue(input).map {
					Pair(UUID.fromString(it), ops.empty())
				}.get().map(
					{
						DataResult.success(it)
					},
					{
						DataResult.error { "Unable to deserialize UUID: ${e0.message()}; ${it.message()}" }
					}
				)
			}
		)
	}
}
