package speiger.src.coreengine.rendering.tesselation.buffer;

import java.util.List;

import speiger.src.coreengine.rendering.tesselation.format.VertexElement;
import speiger.src.coreengine.rendering.tesselation.format.VertexElement.Usage;
import speiger.src.coreengine.rendering.utils.values.GLMode;

public interface IVertexBuilder extends IVertexBuffer {
	public VertexElement current();
	public IVertexBuilder nextElement();
	public IVertexBuilder endDrawCall(boolean store);
	public List<BufferDrawCall> getDrawCalls();
	
	public IVertexBuilder put(int offset, byte value);
	public IVertexBuilder putShort(int offset, short value);
	public IVertexBuilder putInt(int offset, int value);
	public IVertexBuilder putFloat(int offset, float value);
	
	public int size();
	
	@Override
	default IVertexBuffer pos(float x, float y) {
		validate(this, Usage.POS, 2);
		putFloat(0, x);
		putFloat(4, y);
		nextElement();
		return this;
	}
	@Override
	default IVertexBuffer pos(float x, float y, float z) {
		validate(this, Usage.POS, 3);
		putFloat(0, x);
		putFloat(4, y);
		putFloat(8, z);
		nextElement();
		return this;
	}
	@Override
	default IVertexBuffer rgb(int r, int g, int b) {
		validate(this, Usage.COLOR, 3);
		put(0, (byte)r);
		put(1, (byte)g);
		put(2, (byte)b);
		nextElement();
		return this;
	}
	@Override
	default IVertexBuffer rgba(int r, int g, int b, int a) {
		validate(this, Usage.COLOR, 4);
		put(0, (byte)r);
		put(1, (byte)g);
		put(2, (byte)b);
		put(3, (byte)a);
		nextElement();
		return this;
	}
	@Override
	default IVertexBuffer tex(float u, float v) {
		validate(this, Usage.UV, 2);
		putFloat(0, u);
		putFloat(4, v);
		nextElement();
		return this;
	}
	@Override
	default IVertexBuffer normal(float x, float y, float z) {
		validate(this, Usage.NORMAL, 3);
		putFloat(0, x);
		putFloat(4, y);
		putFloat(8, z);
		nextElement();
		return this;
	}
	
	public static void validate(IVertexBuilder builder, VertexElement.Usage usage, int size) {
		VertexElement element = builder.current();
		if(element.usage() != usage || element.size() != size) {
			throw new IllegalStateException("Expected State [Usage="+element.usage()+", Size="+element.size()+"], wasn't present. Actual State [Usage="+usage+", Size="+size+"]");
		}
	}
	
	public record BufferDrawCall(GLMode mode, int startVertex, int endVertex) {
		
	}

}
