package ru.dbotthepony.mc.otm.core.nbt

import net.minecraft.nbt.CompoundTag
import java.util.*
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

@JvmInline
value class CompoundTagInt(val tag: CompoundTag) : ReadWriteProperty<Any, Int> {
	override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getInt(property.name)
	override fun setValue(thisRef: Any, property: KProperty<*>, value: Int) = tag.putInt(property.name, value)
}

@JvmInline
value class CompoundTagLong(val tag: CompoundTag) : ReadWriteProperty<Any, Long> {
	override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getLong(property.name)
	override fun setValue(thisRef: Any, property: KProperty<*>, value: Long) = tag.putLong(property.name, value)
}

@JvmInline
value class CompoundTagByte(val tag: CompoundTag) : ReadWriteProperty<Any, Byte> {
	override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getByte(property.name)
	override fun setValue(thisRef: Any, property: KProperty<*>, value: Byte) = tag.putByte(property.name, value)
}

@JvmInline
value class CompoundTagShort(val tag: CompoundTag) : ReadWriteProperty<Any, Short> {
	override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getShort(property.name)
	override fun setValue(thisRef: Any, property: KProperty<*>, value: Short) = tag.putShort(property.name, value)
}

@JvmInline
value class CompoundTagFloat(val tag: CompoundTag) : ReadWriteProperty<Any, Float> {
	override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getFloat(property.name)
	override fun setValue(thisRef: Any, property: KProperty<*>, value: Float) = tag.putFloat(property.name, value)
}

@JvmInline
value class CompoundTagBoolean(val tag: CompoundTag) : ReadWriteProperty<Any, Boolean> {
	override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getBoolean(property.name)
	override fun setValue(thisRef: Any, property: KProperty<*>, value: Boolean) = tag.putBoolean(property.name, value)
}

@JvmInline
value class CompoundTagDouble(val tag: CompoundTag) : ReadWriteProperty<Any, Double> {
	override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getDouble(property.name)
	override fun setValue(thisRef: Any, property: KProperty<*>, value: Double) = tag.putDouble(property.name, value)
}

@JvmInline
value class CompoundTagString(val tag: CompoundTag) : ReadWriteProperty<Any, String> {
	override fun getValue(thisRef: Any, property: KProperty<*>): String = tag.getString(property.name)
	override fun setValue(thisRef: Any, property: KProperty<*>, value: String) = tag.putString(property.name, value)
}

val EMPTY_UUID = UUID(0L, 0L)

@JvmInline
value class CompoundTagUUID(val tag: CompoundTag) : ReadWriteProperty<Any, UUID> {
	override fun getValue(thisRef: Any, property: KProperty<*>): UUID = if (tag.hasUUID(property.name)) tag.getUUID(property.name) else EMPTY_UUID
	override fun setValue(thisRef: Any, property: KProperty<*>, value: UUID) = tag.putUUID(property.name, value)
}

val CompoundTag.ints get() = CompoundTagInt(this)
val CompoundTag.longs get() = CompoundTagLong(this)
val CompoundTag.bytes get() = CompoundTagByte(this)
val CompoundTag.shorts get() = CompoundTagShort(this)
val CompoundTag.floats get() = CompoundTagFloat(this)
val CompoundTag.doubles get() = CompoundTagDouble(this)
val CompoundTag.booleans get() = CompoundTagBoolean(this)
val CompoundTag.strings get() = CompoundTagString(this)
val CompoundTag.uuids get() = CompoundTagUUID(this)
