package ru.dbotthepony.mc.otm.registry

import com.mojang.serialization.Lifecycle
import net.minecraft.core.Holder
import net.minecraft.core.Registry
import net.minecraft.core.WritableRegistry
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.DyeColor
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import kotlin.reflect.KProperty

operator fun <T : Any> RegistryObject<T>.getValue(thisRef: Any, property: KProperty<*>): T {
	return get()
}

private fun <T> DeferredRegister<T>.doColored(prefix: String, factory: (color: DyeColor, name: String) -> T): MutableCollection<Pair<DyeColor, () -> T>> {
	return mutableListOf(
		DyeColor.BLACK to register(prefix + "_black") { factory.invoke(DyeColor.BLACK, prefix + "_black") }::get,
		DyeColor.BLUE to register(prefix + "_blue") { factory.invoke(DyeColor.BLUE, prefix + "_blue") }::get,
		DyeColor.BROWN to register(prefix + "_brown") { factory.invoke(DyeColor.BROWN, prefix + "_brown") }::get,
		DyeColor.CYAN to register(prefix + "_cyan") { factory.invoke(DyeColor.CYAN, prefix + "_cyan") }::get,
		DyeColor.GRAY to register(prefix + "_gray") { factory.invoke(DyeColor.GRAY, prefix + "_gray") }::get,
		DyeColor.GREEN to register(prefix + "_green") { factory.invoke(DyeColor.GREEN, prefix + "_green") }::get,
		DyeColor.LIGHT_BLUE to register(prefix + "_light_blue") { factory.invoke(DyeColor.LIGHT_BLUE, prefix + "_light_blue") }::get,
		DyeColor.LIGHT_GRAY to register(prefix + "_light_gray") { factory.invoke(DyeColor.LIGHT_GRAY, prefix + "_light_gray") }::get,
		DyeColor.LIME to register(prefix + "_lime") { factory.invoke(DyeColor.LIME, prefix + "_lime") }::get,
		DyeColor.MAGENTA to register(prefix + "_magenta") { factory.invoke(DyeColor.MAGENTA, prefix + "_magenta") }::get,
		DyeColor.ORANGE to register(prefix + "_orange") { factory.invoke(DyeColor.ORANGE, prefix + "_orange") }::get,
		DyeColor.PINK to register(prefix + "_pink") { factory.invoke(DyeColor.PINK, prefix + "_pink") }::get,
		DyeColor.PURPLE to register(prefix + "_purple") { factory.invoke(DyeColor.PURPLE, prefix + "_purple") }::get,
		DyeColor.RED to register(prefix + "_red") { factory.invoke(DyeColor.RED, prefix + "_red") }::get,
		DyeColor.WHITE to register(prefix + "_white") { factory.invoke(DyeColor.WHITE, prefix + "_white") }::get,
		DyeColor.YELLOW to register(prefix + "_yellow") { factory.invoke(DyeColor.YELLOW, prefix + "_yellow") }::get,
	)
}

internal fun <T> DeferredRegister<T>.colored(prefix: String, factory: (color: DyeColor, name: String) -> T): Map<DyeColor, T> {
	return SupplierMap(doColored(prefix, factory))
}

@Suppress("unchecked_cast")
internal fun <T> DeferredRegister<T>.allColored(prefix: String, factory: (color: DyeColor?, name: String) -> T): Map<DyeColor?, T> {
	return SupplierMap(doColored(prefix, factory).also { (it as MutableCollection<Pair<DyeColor?, () -> T>>).add((null as DyeColor?) to register(prefix) { factory.invoke(null, prefix) }::get) })
}

internal fun <T> Registry<T>.register(key: String, value: T): Holder<T> {
	return this.register(ResourceLocation(OverdriveThatMatters.MOD_ID, key), value)
}

internal fun <T> Registry<T>.register(key: ResourceLocation, value: T): Holder<T> {
	return (this as WritableRegistry<T>).register(ResourceKey.create(key(), key), value, Lifecycle.stable())
}
