package ru.dbotthepony.kstarbound.client.render

import org.lwjgl.opengl.GL45
import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram
import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder

/**
 * mesh is container for paired VAO, VBO and EBO, and metadata for them
 */
class Mesh() {
	constructor(builder: VertexBuilder) : this() {
		load(builder, GL45.GL_STATIC_DRAW)
	}

	val state = StarboundClient.current()

	val vao = state.newVAO()
	val vbo = state.newVBO()
	val ebo = state.newEBO()

	init {
		vao.elementBuffer = ebo
	}

	var indexCount = 0
		private set
	var indexType = 0
		private set

	fun load(builder: VertexBuilder, mode: Int = GL45.GL_DYNAMIC_DRAW) {
		builder.upload(vbo, ebo, mode)

		vao.bindAttributes(vbo, builder.attributes)

		indexCount = builder.indexCount
		indexType = builder.indexType
	}

	fun render() {
		vao.bind()
		GL45.glDrawElements(GL45.GL_TRIANGLES, indexCount, indexType, 0L)
		checkForGLError()
		vao.unbind()
	}
}

/**
 * Mesh + RenderConfig
 */
data class ConfiguredMesh<T : GLShaderProgram>(val config: RenderConfig<T>, val mesh: Mesh = Mesh()) {
	fun render() {
		config.setup()
		mesh.render()
		config.uninstall()
	}
}
