package ru.dbotthepony.mc.otm.registry

import net.minecraft.core.Registry
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraftforge.registries.ForgeRegistry
import net.minecraftforge.registries.IForgeRegistry
import net.minecraftforge.registries.NewRegistryEvent
import net.minecraftforge.registries.RegistryBuilder
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import java.util.function.Supplier
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

class RegistryDelegate<T>(key: String, private val configurator: RegistryBuilder<T>.() -> Unit = {}) : ReadOnlyProperty<Any, ForgeRegistry<T>>, Supplier<ForgeRegistry<T>>, Lazy<ForgeRegistry<T>> {
	private var _value: Supplier<IForgeRegistry<T>?>? = null

	override val value: ForgeRegistry<T>
		get() = get()

	override fun isInitialized(): Boolean {
		return _value != null
	}

	val location = ResourceLocation(OverdriveThatMatters.MOD_ID, key)
	val key: ResourceKey<Registry<T>> = ResourceKey.createRegistryKey(location)

	override fun get(): ForgeRegistry<T> {
		val supp = _value ?: throw IllegalStateException("Tried to access uninitialized registry $location")
		return supp.get() as ForgeRegistry<T>? ?: throw IllegalStateException("Accessing registry $location too early")
	}

	override fun getValue(thisRef: Any, property: KProperty<*>): ForgeRegistry<T> {
		return get()
	}

	fun build(event: NewRegistryEvent) {
		if (_value != null) {
			throw IllegalStateException("Already built registry $location!")
		}

		_value = RegistryBuilder<T>().let {
			it.setName(location)
			// it.type = AndroidFeatureType::class.java
			configurator.invoke(it)
			event.create(it)
		}
	}
}
