package ru.dbotthepony.kstarbound.json.factory

import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.reflect.TypeToken
import ru.dbotthepony.kstarbound.json.builder.JsonSingleton
import ru.dbotthepony.kstarbound.json.builder.SingletonTypeAdapter

object SingletonTypeAdapterFactory : TypeAdapterFactory {
	override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
		val raw = type.rawType

		if (raw.isAnnotationPresent(JsonSingleton::class.java)) {
			val findInstance = raw.getDeclaredField("INSTANCE")
			val f = findInstance.get(null) ?: throw NullPointerException("INSTANCE field is null")

			if (!raw.isAssignableFrom(f::class.java)) {
				throw ClassCastException("${f::class.java} can not be assigned to $raw")
			}

			return SingletonTypeAdapter(f) as TypeAdapter<T>
		}

		return null
	}
}
