package com.danitheskunk.skunkworks.backends.gl;

import com.danitheskunk.skunkworks.Vec2f;
import com.danitheskunk.skunkworks.Vec3f;
import com.danitheskunk.skunkworks.gfx.threedee.BaseRenderContext3D;
import com.danitheskunk.skunkworks.gfx.threedee.Mesh;

import static org.lwjgl.opengl.GL46.*;

public class RenderContext3D extends BaseRenderContext3D {
	private final int texCoordIndex;
	private TextureAtlas textureAtlas;

	public RenderContext3D(int texCoordIndex) {
		this.texCoordIndex = texCoordIndex;
	}


	@Override
	public void renderMesh(Mesh mesh) {
		var tex = (Texture) mesh.getTexture();

		var texArea = tex.getTexArea();
		var texOff = Vec2f.div(texArea.getPos(), textureAtlas.getSize());
		var texMult = Vec2f.div(texArea.getSize(), textureAtlas.getSize());


		glBegin(GL_TRIANGLES);
		for(int i = 0; i < mesh.getTriangleCount(); ++i) {
			var tri = mesh.getTriangle(i);
			var p1 = mesh.getVertex(tri.getX());
			var p2 = mesh.getVertex(tri.getY());
			var p3 = mesh.getVertex(tri.getZ());
			var t1 = mesh.getUV(tri.getX());
			var t2 = mesh.getUV(tri.getY());
			var t3 = mesh.getUV(tri.getZ());

			assert (t1.getX() >= 0.0 && t1.getX() <= 1.0);
			assert (t1.getY() >= 0.0 && t1.getY() <= 1.0);
			assert (t2.getX() >= 0.0 && t2.getX() <= 1.0);
			assert (t2.getY() >= 0.0 && t2.getY() <= 1.0);
			assert (t3.getX() >= 0.0 && t3.getX() <= 1.0);
			assert (t3.getY() >= 0.0 && t3.getY() <= 1.0);

			t1 = Vec2f.add(texOff, Vec2f.mul(texMult, t1));
			t2 = Vec2f.add(texOff, Vec2f.mul(texMult, t2));
			t3 = Vec2f.add(texOff, Vec2f.mul(texMult, t3));




			glVertexAttrib2d(texCoordIndex, t1.getX(), t1.getY());
			glVertex3d(p1.getX(), p1.getY() - 0.5, p1.getZ() + 0.5);
			glVertexAttrib2d(texCoordIndex, t2.getX(), t2.getY());
			glVertex3d(p2.getX(), p2.getY() - 0.5, p2.getZ() + 0.5);
			glVertexAttrib2d(texCoordIndex, t3.getX(), t3.getY());
			glVertex3d(p3.getX(), p3.getY() - 0.5, p3.getZ() + 0.5);
		}
		glEnd();
	}

	@Override
	public void renderTriangle(Vec3f p1, Vec3f p2, Vec3f p3) {
		glBegin(GL_TRIANGLES);

		glVertex3d(p1.getX(), p1.getY(), p1.getZ());
		glVertex3d(p2.getX(), p2.getY(), p2.getZ());
		glVertex3d(p3.getX(), p3.getY(), p3.getZ());

		glEnd();
	}

	public void setTextureAtlas(TextureAtlas textureAtlas) {
		this.textureAtlas = textureAtlas;
	}
}
