package speiger.src.coreengine.rendering.utils.values.textures;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;

import speiger.src.coreengine.rendering.utils.values.IGLValue.ITextureComponentFormat;

public enum GLTextureFormat implements ITextureComponentFormat {
	R(GL11.GL_RED, 1, 0, -1, -1, -1, false),
	RG(GL30.GL_RG, 2, 0, 1, -1, -1, false),
	RGB(GL11.GL_RGB, 3, 0, 1, 2, -1, false),
	RGBI(GL11.GL_RGB8, 3, 0, 1, 2, -1, true),
	RGBA(GL11.GL_RGBA, 4, 0, 1, 2, 3, false),
	RGBAI(GL11.GL_RGBA8, 4, 0, 1, 2, 3, true),
	DEPTH(GL11.GL_DEPTH_COMPONENT, 1, 0, -1, -1, -1, false),
	DEPTH_STENCIL(GL30.GL_DEPTH_STENCIL, 2, 0, 1, -1, -1, false),
	LUMINANCE(GL30.GL_R8, 1, 0, 0, 0, 0, true),
	LUMINANCE_ALPHA(GL11.GL_LUMINANCE8_ALPHA8, 2, 0, -1, -1, 1, true);
	
	int glMode;
	boolean internal;
	
	int components;
	int componentMask;
	int redOffset;
	int greenOffset;
	int blueOffset;
	int alphaOffset;
	
	private GLTextureFormat(int glMode, int components, int redOffset, int greenOffset, int blueOffset, int alphaOffset, boolean internal) {
		this.glMode = glMode;
		this.components = components;
		this.componentMask = (1 << (components * 8)) - 1;
		this.redOffset = redOffset;
		this.greenOffset = greenOffset;
		this.blueOffset = blueOffset;
		this.alphaOffset = alphaOffset;
		this.internal = internal;
	}
	
	@Override
	public int glValue() { return glMode; }
	@Override
	public boolean internal() { return internal; }
	@Override
	public int components() { return stbComponents(glMode); }
	@Override
	public int componentMask() { return componentMask; }
	
	public int redOffset() { return redOffset; }
	public int greenOffset() { return greenOffset; }
	public int blueOffset() { return blueOffset; }
	public int alphaOffset() { return alphaOffset; }
	
	public static int stbComponents(int glValue) {
		return switch(glValue) {
			case GL30.GL_R8, GL11.GL_RED -> 1;
			case GL11.GL_LUMINANCE8_ALPHA8, GL30.GL_RG -> 2;
			case GL11.GL_RGB -> 3;
			case GL11.GL_RGBA -> 4;			
			default -> 0;
		};
	}
	
	public static GLTextureFormat bySTB(int components) {
		return switch(components) {
			case 1 -> LUMINANCE;
			case 2 -> LUMINANCE_ALPHA;
			case 3 -> RGB;
			case 4 -> RGBA;
			default -> throw new IllegalArgumentException("Only 1-4 Components are supported");
		};
	}
}
