package speiger.src.coreengine.rendering.models;

import java.util.Map;

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

import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;

public class GLDataType
{
	static final Int2ObjectMap<GLDataType> ID_TO_TYPE = new Int2ObjectOpenHashMap<>();
	static final Map<String, GLDataType> NAME_TO_TYPE = new Object2ObjectOpenHashMap<>();
	//Normal Types
	public static final GLDataType BYTE = new GLDataType(GL11.GL_BYTE, DataType.BYTE, "byte");
	public static final GLDataType UNSIGNED_BYTE = new GLDataType(GL11.GL_UNSIGNED_BYTE, DataType.BYTE, "u_byte");
	public static final GLDataType SHORT = new GLDataType(GL11.GL_SHORT, DataType.SHORT, "short");
	public static final GLDataType UNSIGNED_SHORT = new GLDataType(GL11.GL_UNSIGNED_SHORT, DataType.SHORT, "u_short");
	public static final GLDataType INT = new GLDataType(GL11.GL_INT, DataType.INT, "int");
	public static final GLDataType UNSIGNED_INT = new GLDataType(GL11.GL_UNSIGNED_INT, DataType.INT, "u_int");
	public static final GLDataType FLOAT = new GLDataType(GL11.GL_FLOAT, DataType.FLOAT, "float");
	public static final GLDataType DOUBLE = new GLDataType(GL11.GL_DOUBLE, DataType.DOUBLE, "double");
	
	
	//Compression Types
	public static final GLDataType UNSIGNED_INT_10_10_10_2 = new GLDataType(GL12.GL_UNSIGNED_INT_10_10_10_2, DataType.INT, true, "u_int_10_10_10_2");
	public static final GLDataType UNSIGNED_INT_2_10_10_10_REV = new GLDataType(GL12.GL_UNSIGNED_INT_2_10_10_10_REV, DataType.INT, true, "u_int_2_10_10_10_rev");
	
	//Special Types
	public static final GLDataType UNSIGNED_INT_10F_11F_11F_REV = new GLDataType(GL30.GL_UNSIGNED_INT_10F_11F_11F_REV, DataType.INT, true, "u_int_10_11_11_rev");
	public static final GLDataType UNSIGNED_INT_5_9_9_9_REV = new GLDataType(GL30.GL_UNSIGNED_INT_5_9_9_9_REV, DataType.INT, true, "u_int_5_9_9_9_rev");
	
	final int glType;
	final DataType dataType;
	final boolean ignoreAttributeSize;
	final String name;
	
	public GLDataType(int glType, DataType dataType, String name)
	{
		this(glType, dataType, false, name);
	}
	
	public GLDataType(int glType, DataType dataType, boolean ignoreAttributeSize, String name)
	{
		this.glType = glType;
		this.dataType = dataType;
		this.ignoreAttributeSize = ignoreAttributeSize;
		this.name = name;
		ID_TO_TYPE.put(glType, this);
		NAME_TO_TYPE.put(name, this);
	}
	
	public int getGLType()
	{
		return glType;
	}
	
	public String getName()
	{
		return name;
	}
	
	public int getByteSize()
	{
		return dataType.getByteSize();
	}
	
	public boolean isSpecialType()
	{
		return ignoreAttributeSize;
	}
	
	public DataType getDataType()
	{
		return dataType;
	}
	
	public int calulateSize(int attributeSize)
	{
		return ignoreAttributeSize ? dataType.getByteSize() : attributeSize * dataType.getByteSize();
	}
	
	public static GLDataType byName(String name)
	{
		return NAME_TO_TYPE.get(name);
	}
	
	public static GLDataType byID(int id)
	{
		return ID_TO_TYPE.get(id);
	}
}
