package ru.dbotthepony.kstarbound.client.gl

import org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT0
import org.lwjgl.opengl.GL30.GL_FRAMEBUFFER
import org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_COMPLETE
import org.lwjgl.opengl.GL30.GL_LINEAR
import org.lwjgl.opengl.GL30.GL_RGB
import org.lwjgl.opengl.GL30.GL_TEXTURE_2D
import org.lwjgl.opengl.GL30.glFramebufferTexture2D
import org.lwjgl.opengl.GL45.glCheckNamedFramebufferStatus
import org.lwjgl.opengl.GL45
import ru.dbotthepony.kstarbound.client.StarboundClient

class GLFrameBuffer : GLObject() {
	override val client = StarboundClient.current()
	override val pointer = GL45.glGenFramebuffers()

	init {
		checkForGLError("Creating framebuffer")
		client.registerCleanable(this, GL45::glDeleteFramebuffers, pointer)
	}

	val isComplete: Boolean get() {
		client.ensureSameThread()
		return glCheckNamedFramebufferStatus(pointer, GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE
	}

	var texture: GLTexture2D? = null
		private set

	fun attachTexture(width: Int, height: Int, format: Int = GL_RGB) {
		if (texture != null) {
			throw IllegalStateException("Already has texture attached")
		}

		val texture = GLTexture2D(width, height, format)

		val old = client.framebuffer
		bind()
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.pointer, 0)
		checkForGLError()
		this.texture = texture
		texture.textureMinFilter = GL_LINEAR
		client.framebuffer = old
	}

	fun reattachTexture(width: Int, height: Int, format: Int = GL_RGB) {
		texture = null
		attachTexture(width, height, format)
	}

	override fun bind() {
		client.framebuffer = this
	}

	override fun unbind() {
		if (client.framebuffer == this)
			client.framebuffer = null
	}
}
