package speiger.src.coreengine.rendering.utils;

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

import speiger.src.coreengine.rendering.textures.base.TextureMetadata;
import speiger.src.coreengine.rendering.utils.values.IGLValue;
import speiger.src.coreengine.rendering.utils.values.IGLValue.IGLDataType;
import speiger.src.coreengine.rendering.utils.values.IGLValue.ITextureFormatType;
import speiger.src.coreengine.rendering.utils.values.IGLValue.ITextureParameter;

public class GLFunctions {
	
	public static int createTexture(IGLValue textureType) {
		return GL45.glCreateTextures(textureType.glValue());
	}
	
	public static void deleteTextures(int... id) {
		GL11.glDeleteTextures(id);
	}
	
	public static void textureParameter(int texture, ITextureParameter parameter, IGLValue value) {
		textureParameter(texture, parameter, value.glValue());
	}
	
	public static void textureParameter(int texture, ITextureParameter parameter, int value) {
		if(!parameter.isValid(value)) throw new IllegalArgumentException("Value ["+value+"] isn't supported for GL Function ["+parameter.glValue()+"], only int functions are supported with this");
		textureParameter(texture, parameter.glValue(), value);
	}
	
	public static void textureParameter(int texture, int parameter, int value) {
		GL45.glTextureParameteri(texture, parameter, value);
	}
	
	public static void prepare2DImage(int texture, int levels, TextureMetadata metadata, int width, int height) {
		GL45.glTextureStorage2D(texture, levels, metadata.getInternalFormat(), width, height);
	}
	
	public static void upload2DImage(int texture, int mipmaps, TextureMetadata metadata, int width, int height, int border, long pixels) {
		upload2DImage(texture, mipmaps, metadata.getInternalFormat(), width, width, border, metadata.getExternalFormat(), metadata.getDataFormat(), pixels);
	}
	
	public static void upload2DImage(int texture, int mipmaps, ITextureFormatType internalFormat, int width, int height, int border, ITextureFormatType externalFormat, IGLDataType data, long pixels) {
		upload2DImage(texture, mipmaps, internalFormat.glValue(), width, height, border, externalFormat.glValue(), data.glValue(), pixels);
	}
	
	public static void upload2DImage(int texture, int mipmaps, int internalFormat, int width, int height, int border, int externalFormat, int dataFormat, long pixels) {
		GL45.glTextureStorage2D(texture, mipmaps+1, internalFormat, width, height);
		GL45.glTextureSubImage2D(texture, mipmaps, 0, 0, width, height, externalFormat, dataFormat, pixels);
	}
	
	
	public static void upload2DSubImage(int texture, int level, int xoffset, int yoffset, int width, int height, ITextureFormatType format, IGLDataType type, long pixels) {
//		if(format.internal()) throw new IllegalArgumentException("Format ["+format.glValue()+"] is internal");
		upload2DSubImage(texture, level, xoffset, yoffset, width, height, format.glValue(), type.glValue(), pixels);
	}
	
	public static void upload2DSubImage(int texture, int level, int xOffset, int yOffset, int width, int height, int format, int type, long pixels) {
		GL45.glTextureSubImage2D(texture, level, xOffset, yOffset, width, height, format, type, pixels);
	}
	
	public static void generateMipMaps(IGLValue type) {
		GL30.glGenerateMipmap(type.glValue());
	}
		
	public static void pixelStoreI(int mode, int value) {
		GL11.glPixelStorei(mode, value);
	}
}
