package gay.pizza.CavesOfJolk

import com.badlogic.gdx.graphics.g3d.Attributes
import com.badlogic.gdx.graphics.g3d.Renderable
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute
import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader

class CustomDefaultShader(renderable: Renderable, config: Config):
	DefaultShader(renderable, config, createPrefix(renderable, config))
{
	companion object
	{
		fun createPrefix(renderable: Renderable, config: Config): String
		{
			var prefix = DefaultShader.createPrefix(renderable, config)

			val attribs = Attributes()
			renderable.environment.let { attribs.set(it) }
			renderable.material.let { attribs.set(it) }

			if (attribs.has(ColorAttribute.Fog))
			{
				prefix += "#define fog${
					when (attribs.get<CustomIntAttribute>(CustomIntAttribute.FogMode)?.value
							?: CustomIntAttribute.FogModes.Distance.toInt()) {
						CustomIntAttribute.FogModes.Distance.toInt() -> "Distance"
						CustomIntAttribute.FogModes.Depth.toInt()    -> "Depth"
						else -> throw IndexOutOfBoundsException()
					}
				}Flag\n"
				prefix += "#define fog${
					when (attribs.get<CustomIntAttribute>(CustomIntAttribute.FogType)?.value
							?: CustomIntAttribute.FogTypes.Original.toInt()) {
						CustomIntAttribute.FogTypes.Original.toInt()  -> "Original"
						CustomIntAttribute.FogTypes.Linear.toInt()    -> "Linear"
						CustomIntAttribute.FogTypes.Smooth.toInt()    -> "Smooth"
						CustomIntAttribute.FogTypes.InvSquare.toInt() -> "InvSquare"
						CustomIntAttribute.FogTypes.Exp.toInt()       -> "Exp"
						CustomIntAttribute.FogTypes.Exp2.toInt()      -> "Exp2"
						else -> throw IndexOutOfBoundsException()
					}
				}Flag\n"
			}

			return prefix
		}

		object Inputs
		{
			val fogNear    = Uniform("u_fogNear")
			val fogFar     = Uniform("u_fogFar")
			val fogDensity = Uniform("u_fogDensity")
		}
	}

	private val u_fogNear    = register(Inputs.fogNear)
	private val u_fogFar     = register(Inputs.fogFar)
	private val u_fogDensity = register(Inputs.fogDensity)

	override fun bindLights(renderable: Renderable?, attributes: Attributes?)
	{
		if (attributes == null)
			return

		attributes.get<CustomFloatAttribute>(CustomFloatAttribute.FogNear)?.let { set(u_fogNear, it.value) }
		attributes.get<CustomFloatAttribute>(CustomFloatAttribute.FogFar)?.let { set(u_fogFar, it.value) }
		attributes.get<CustomFloatAttribute>(CustomFloatAttribute.FogDensity)?.let { set(u_fogDensity, it.value) }

		super.bindLights(renderable, attributes)
	}
}
