package speiger.src.coreengine.rendering.guiOld.renderer;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import org.lwjgl.opengl.GL11;
import org.lwjgl.system.MemoryUtil;

import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.queues.ObjectArrayFIFOQueue;
import speiger.src.collections.objects.queues.ObjectPriorityDequeue;
import speiger.src.collections.utils.Stack;
import speiger.src.coreengine.assets.reloader.IReloadableResource;
import speiger.src.coreengine.math.misc.Facing;
import speiger.src.coreengine.math.vector.floats.Vec2f;
import speiger.src.coreengine.math.vector.floats.Vec3f;
import speiger.src.coreengine.math.vector.floats.Vec4f;
import speiger.src.coreengine.math.vector.matrix.Matrix4f;
import speiger.src.coreengine.math.vector.quaternion.Quaternion;
import speiger.src.coreengine.rendering.guiOld.GuiManager;
import speiger.src.coreengine.rendering.guiOld.helper.Align;
import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox;
import speiger.src.coreengine.rendering.guiOld.renderer.buffer.RenderBuffer;
import speiger.src.coreengine.rendering.models.DrawCall;
import speiger.src.coreengine.rendering.shaderOld.uniforms.UniformVec2f;
import speiger.src.coreengine.rendering.tesselation.GLCall;
import speiger.src.coreengine.rendering.tesselationOld.Tesselator;
import speiger.src.coreengine.rendering.tesselationOld.VertexType;
import speiger.src.coreengine.rendering.texturesOld.base.ITexture;
import speiger.src.coreengine.rendering.texturesOld.base.TextureManager;
import speiger.src.coreengine.rendering.utils.GLStateTracker;
import speiger.src.coreengine.utils.collections.pools.SimplePool;

public class UIRenderer implements IReloadableResource
{
	SimplePool<Matrix4f> recylcePool = new SimplePool<>(100, Matrix4f::new);
	Stack<Matrix4f> transformStack = new ObjectArrayList<>();
	Matrix4f transform = new Matrix4f();
	boolean isFastTransform = true;
	SimplePool<Vec4f> fastPool = new SimplePool<>(100, Vec4f::of);
	Stack<Vec4f> fastStack = new ObjectArrayList<>();
	Vec4f fastTransform = Vec4f.mutable(0F, 0F, 0F, 1F);
	
	SimplePool<GLCall> callPool = new SimplePool<>(100, GLCall::new);
	ObjectPriorityDequeue<GLCall> activeCalls = new ObjectArrayFIFOQueue<>();
	
	Tesselator bufferHelper = new Tesselator(655340);
	FloatBuffer renderBuffer = MemoryUtil.memAllocFloat(655340);
	Tesselator renderer = new Tesselator(renderBuffer);
	ITexture currentTexture;
	boolean drawing = false;
	boolean useTexture = false;
	Vec4f currentFrame = Vec4f.mutable();
	float roundedNess = 0F;
	
	GuiModel texturedModel = GuiModel.createTextureModel(Short.MAX_VALUE * 2);	
	
	Align horizontal = Align.CENTER;
	Align vertical = Align.CENTER;
	
	Vec3f helper = Vec3f.mutable();
	Vec4f transformHelper = Vec4f.mutable();
	Vec4f alignHelper = Vec4f.mutable();
	Vec3f alignTranslation = Vec3f.mutable(0F);
	Vec3f alignScale = Vec3f.mutable(1F);
		
	GuiManager manager;
	
	public UIRenderer(GuiManager manager)
	{
		this.manager = manager;
		TextureManager.INSTANCE.getReloader().addReloadableResource(this);
	}
	
	public RenderBuffer createBuffer()
	{
		return new RenderBuffer(bufferHelper);
	}
	
	public UIRenderer push()
	{
		if(isFastTransform) fastStack.push(fastPool.get().set(fastTransform));
		else transformStack.push(recylcePool.get().load(transform));
		return this;
	}
	
	public UIRenderer pop()
	{
		if(isFastTransform)
		{
			Vec4f pop = fastStack.pop();
			fastTransform.set(pop);
			fastPool.accept(pop);
			return this;
		}
		Matrix4f pop = transformStack.pop();
		transform.load(pop);
		pop.getScale(alignScale);
		recylcePool.accept(pop);
		return this;
	}
	
	public UIRenderer setVisibility(float visibility)
	{
		sanityCheck("Visibilty Change");
		renderer.setVisibilty(visibility);
		return this;
	}
	
	public UIRenderer setBrightness(float brightness)
	{
		sanityCheck("Brightness change");
		renderer.setBrightness(brightness);
		return this;
	}
	
	public UIRenderer resetEffects()
	{
		renderer.setBrightness(1F).setVisibilty(1F);
		return this;
	}
	
	public UIRenderer setActiveTexture(ITexture texture)
	{
		if(getTextureId(currentTexture) != getTextureId(texture))
		{
			addDrawCall();
			currentTexture = texture;
		}
		return this;
	}
	
	public UIRenderer setRoundness(IGuiBox box, float roundedNess)
	{
		if(roundedNess <= 0)
		{
			if(this.roundedNess > 0F) addDrawCall();
			this.roundedNess = roundedNess;
			return this;
		}
		alignHelper.set(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY());
		if(!currentFrame.equals(alignHelper) || this.roundedNess != roundedNess)
		{
			addDrawCall();
			currentFrame.set(alignHelper);
			this.roundedNess = roundedNess;
		}
		return this;
	}
		
	protected void applyEffects(UniformVec2f vec)
	{
		vec.storeData(renderer.getBrightness(), renderer.getVisibility());
	}
	
	public UIRenderer translate(float x, float y)
	{
		return translate(x, y, 0F);
	}
	
	public UIRenderer translate(Vec2f offset)
	{
		return translate(offset.x(), offset.y(), 0F);
	}
	
	public UIRenderer translate(float x, float y, float z)
	{
		if(isFastTransform)
		{
			fastTransform.add(x, y, z, 0F);
			return this;
		}
		transform.translate(x, y, z);
		return this;
	}
	
	public UIRenderer translate(Vec3f offset)
	{
		if(isFastTransform)
		{
			fastTransform.add(offset.x(), offset.y(), offset.z(), 0F);
			return this;
		}
		transform.translate(offset.x(), offset.y(), offset.z());
		return this;
	}
	
	public UIRenderer rotate(Quaternion quad)
	{
		if(isFastTransform) return this;
		transform.rotate(quad);
		return this;
	}
	
	public UIRenderer rotateX(float angle)
	{
		if(isFastTransform) return this;
		transform.rotateX((float)Math.toRadians(angle));
		return this;
	}
	
	public UIRenderer rotateY(float angle)
	{
		if(isFastTransform) return this;
		transform.rotateY((float)Math.toRadians(angle));
		return this;
	}
	
	public UIRenderer rotateZ(float angle)
	{
		if(isFastTransform) return this;
		transform.rotateZ((float)Math.toRadians(angle));
		return this;
	}
	
	public UIRenderer scale(float x, float y, float z)
	{
		if(isFastTransform) return this;
		transform.scale(x, y, z);
		alignScale.multiply(x, y, z);
		return this;
	}
	
	public UIRenderer scale(float scale)
	{
		if(isFastTransform)
		{
			fastTransform.multiply(1F, 1F, 1F, scale);
			return this;
		}
		transform.scale(scale);
		alignScale.multiply(scale);
		return this;
	}
	
	public UIRenderer unscale(float x, float y, float z)
	{
		if(isFastTransform) return this;
		transform.scale(1.0F / x, 1.0F / y, 1.0F / z);
		alignScale.multiply(helper);
		return this;
	}
	
	public UIRenderer unscale(float scale)
	{
		scale = 1.0F / scale;
		if(isFastTransform)
		{
			fastTransform.multiply(1F, 1F, 1F, scale);
			return this;
		}
		transform.scale(scale, scale, scale).getScale(alignScale);
		alignScale.multiply(scale);
		return this;
	}
	
	public UIRenderer resetTransform()
	{
		if(isFastTransform)
		{
			fastTransform.set(0F, 0F, 0F, 1F);
			return this;
		}
		transform.setIdentity();
		alignScale.set(Vec3f.ONE);
		return this;
	}
	
	public float getCurrentZ()
	{
		return isFastTransform ? fastTransform.z() : transform.get(3, 2);
	}
	
	public ITexture getActiveTexture()
	{
		return currentTexture;
	}
	
	protected Matrix4f getCurrentMatrix()
	{
		return transform;
	}
	
	public Matrix4f createCurrentMatrix(Matrix4f matrix)
	{
		return isFastTransform ? matrix.setIdentity().translate(fastTransform.x(), fastTransform.y(), fastTransform.z()) : matrix.load(transform);
	}
	
	public UIRenderer setFastTransform(boolean fast)
	{
		isFastTransform = fast;
		return this;
	}
	
	public UIRenderer beginFrame()
	{
		if(drawing)
		{
			throw new RuntimeException("Already Drawing!");
		}
		drawing = true;
		fastTransform.set(0F, 0F, 0F, 1F);
		roundedNess = 0F;
		currentFrame.negate();
		transform.setIdentity();
		alignScale.set(Vec3f.ONE);
		transformStack.clear();
		fastStack.clear();
		return this;
	}
	
	public UIRenderer flush()
	{
		if(!renderer.isDrawing())
		{
			return this;
		}
		renderer.finishData();
		int count = renderer.getVertexCount();
		if(count <= 0)
		{
			return this;
		}
		if(count > (activeCalls.isEmpty() ? 0 : activeCalls.last().getCount()))
		{
			addDrawCall();
		}
		texturedModel.storeData(renderBuffer);
		GuiShader shader = manager.getShader();
		shader.bind(manager.getOrthoMatrixBuffer());
		texturedModel.bindArray();
		int last = 0;
		while(!activeCalls.isEmpty())
		{
			GLCall call = activeCalls.dequeue();
			shader.texture.storeTexture(call.getTexture());
			shader.useTexture.storeData(call.getTexture() > 0 ? 1F : 0F);
			shader.roundeness.storeData(call.getRoundedNess());
			if(call.getRoundedNess() > 0F) shader.bounds.storeData(call.getFrame());
			GLStateTracker.drawArrays(call.getType(), last, call.getCount() - last);
			last = call.getCount();
			callPool.accept(call);
		}
		texturedModel.unbindArray();
		shader.stopShader();
		renderer.resetVertexes();
		return this;
	}
	
	public UIRenderer endFrame()
	{
		if(!drawing)
		{
			throw new RuntimeException("Not Drawing!");
		}
		drawing = false;
		isFastTransform = true;
		flush();
		fastTransform.set(0F, 0F, 0F, 1F);
		transform.setIdentity();
		renderer.resetEffects();
		useTexture = false;
		while(!transformStack.isEmpty())
		{
			recylcePool.accept(transformStack.pop());
		}
		while(!fastStack.isEmpty())
		{
			fastPool.accept(fastStack.pop());
		}
		return this;
	}
	
	@Override
	public void reload()
	{
		texturedModel.remove();
		MemoryUtil.memFree(renderBuffer);
		texturedModel = GuiModel.createTextureModel(Short.MAX_VALUE * 2);
		renderBuffer = MemoryUtil.memAllocFloat(655340);
		renderer = new Tesselator(renderBuffer);
	}
	
	@Override
	public void destroy()
	{
		texturedModel.remove();
		MemoryUtil.memFree(renderBuffer);
		TextureManager.INSTANCE.getReloader().removeReloadableResource(this);
	}
	
	public UIRenderer drawBuffers(Iterable<DrawCall> drawCalls, float width, float height)
	{
		sanityCheck("Buffer Drawing");
		applyAlignment(0, 0, width, height, 0, alignHelper);
		for(DrawCall call : drawCalls)
		{
			ensureDrawing(call.glType().glValue(), call.textureId() > 0);
			FloatBuffer buffer = ByteBuffer.wrap(call.data()).order(ByteOrder.nativeOrder()).asFloatBuffer();
			for(int i = 0,m=buffer.remaining();i+9<=m;i+=9)
			{
				pos(transformHelper.set(buffer.get(i)+alignHelper.x(), buffer.get(i+1)+alignHelper.y(), buffer.get(i+2), 1F))
				.tex(buffer.get(i+3), buffer.get(i+4))
				.color4f(buffer.get(i+5), buffer.get(i+6), buffer.get(i+7), buffer.get(i+8)).endVertex();
			}
		}
		alignTranslation.set(0F, 0F, 0F);
		return this;
	}
	
	public UIRenderer drawQuad(IGuiBox box, int color)
	{
		return drawQuad(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), color);
	}
	
	public UIRenderer drawQuad(IGuiBox box, float zLevel, int color)
	{
		return drawQuad(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), zLevel, color);
	}
	
	public UIRenderer drawQuad(float minX, float minY, float maxX, float maxY, int color)
	{
		return drawQuad(minX, minY, maxX, maxY, 0.0F, color);
	}
	
	public UIRenderer drawQuad(float minX, float minY, float maxX, float maxY, float zLevel, int color)
	{
		ensureDrawing(GL11.GL_TRIANGLES, false);
		applyAlignment(minX, minY, maxX, maxY, zLevel, alignHelper);
		pos(transformHelper.set(alignHelper.x(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		alignTranslation.set(0F, 0F, 0F);
		return this;
	}
	
	public UIRenderer drawTexturedQuad(IGuiBox box, int color, float minU, float minV, float maxU, float maxV)
	{
		return drawTexturedQuad(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), color, minU, minV, maxU, maxV);
	}
	
	public UIRenderer drawTexturedQuad(IGuiBox box, float zLevel, int color, float minU, float minV, float maxU, float maxV)
	{
		return drawTexturedQuad(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), zLevel, color, minU, minV, maxU, maxV);
	}
	
	public UIRenderer drawTexturedQuad(float minX, float minY, float maxX, float maxY, int color, float minU, float minV, float maxU, float maxV)
	{
		return drawTexturedQuad(minX, minY, maxX, maxY, 0F, color, minU, minV, maxU, maxV);
	}
	
	public UIRenderer drawTexturedQuad(float minX, float minY, float maxX, float maxY, float zLevel, int color, float minU, float minV, float maxU, float maxV)
	{
		ensureDrawing(GL11.GL_TRIANGLES, true);
		applyAlignment(minX, minY, maxX, maxY, zLevel, alignHelper);
		pos(transformHelper.set(alignHelper.x(), alignHelper.w(), 0F, 1F)).tex(minU, maxV).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(minU, minV).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(maxU, maxV).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(maxU, maxV).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(minU, minV).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.y(), 0F, 1F)).tex(maxU, minV).color4f(color).endVertex();
		alignTranslation.set(0F, 0F, 0F);
		return this;
	}
	
	public UIRenderer drawGradientQuad(IGuiBox box, int from, int to, Facing direction)
	{
		return drawGradientQuad(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), from, to, direction);
	}
	
	public UIRenderer drawGradientQuad(float minX, float minY, float maxX, float maxY, int from, int to, Facing direction)
	{
		return drawGradientQuad(minX, minY, maxX, maxY, 0F, from, to, direction);
	}
	
	public UIRenderer drawGradientQuad(float minX, float minY, float maxX, float maxY, float zLevel, int start, int end, Facing direction)
	{
		if(!direction.isPositive())
		{
			int wrapper = start;
			start = end;
			end = wrapper;
		}
		ensureDrawing(GL11.GL_TRIANGLES, false);
		applyAlignment(minX, minY, maxX, maxY, zLevel, alignHelper);	
		pos(transformHelper.set(alignHelper.x(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(direction.isXAxis() ? start : end).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(direction.isXAxis() ? start : start).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(direction.isXAxis() ? end : end).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(direction.isXAxis() ? end : end).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(direction.isXAxis() ? start : start).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(direction.isXAxis() ? end : start).endVertex();
		alignTranslation.set(0F, 0F, 0F);
		return this;
	}
	
	public UIRenderer drawFrame(IGuiBox box, int color)
	{
		return drawFrame(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), color);
	}
	
	public UIRenderer drawFrame(IGuiBox box, float zLevel, int color)
	{
		return drawFrame(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), zLevel, color);
	}
	
	public UIRenderer drawFrame(float minX, float minY, float maxX, float maxY, int color)
	{
		return drawFrame(minX, minY, maxX, maxY, 0F, color);
	}
	
	public UIRenderer drawFrame(float minX, float minY, float maxX, float maxY, float zLevel, int color)
	{
		ensureDrawing(GL11.GL_LINES, false);
		applyAlignment(minX, minY, maxX, maxY, zLevel, alignHelper);
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		alignTranslation.set(0F, 0F, 0F);
		return this;
	}
	
	public UIRenderer drawLine(float minX, float minY, float maxX, float maxY, int color)
	{
		return drawLine(minX, minY, maxX, maxY, 0F, color);
	}
	
	public UIRenderer drawLine(float minX, float minY, float maxX, float maxY, float zLevel, int color)
	{
		ensureDrawing(GL11.GL_LINES, false);
		applyAlignment(minX, minY, maxX, maxY, zLevel, alignHelper);
		pos(transformHelper.set(alignHelper.x(), alignHelper.y(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		pos(transformHelper.set(alignHelper.z(), alignHelper.w(), 0F, 1F)).tex(0F, 0F).color4f(color).endVertex();
		alignTranslation.set(0F, 0F, 0F);
		return this;
	}
	
	public UIRenderer startCustomShape(int shapeType, boolean needsTexture)
	{
		sanityCheck("Custom Shape");
		ensureDrawing(shapeType, needsTexture);
		return this;
	}
	
	public UIRenderer pos(float x, float y, float z)
	{
		pos(transformHelper.set(x, y, z, 1F));
		return this;
	}
	
	public UIRenderer pos(Vec3f pos)
	{
		return pos(pos.x(), pos.y(), pos.z());
	}
	
	public UIRenderer color(float r, float g, float b)
	{
		renderer.color4f(r, g, b);
		return this;
	}
	
	public UIRenderer color(float r, float g, float b, float a)
	{
		renderer.color4f(r, g, b, a);
		return this;
	}
	
	public UIRenderer color(int color)
	{
		renderer.color4f(color);
		return this;
	}
	
	public UIRenderer tex(float u, float v)
	{
		renderer.tex(u, v);
		return this;
	}
	
	public UIRenderer tex(Vec2f tex)
	{
		return tex(tex.x(), tex.y());
	}
	
	public UIRenderer endVertex()
	{
		renderer.endVertex();
		return this;
	}
	
	protected void sanityCheck(String task)
	{
		if(drawing)
		{
			return;
		}
		throw new RuntimeException(task);
	}
	
	protected Tesselator pos(Vec4f pos)
	{
		if(isFastTransform)
		{
			return renderer.pos(fastTransform(pos.x(), fastTransform.x(), alignTranslation.x()), fastTransform(pos.y(), fastTransform.y(), alignTranslation.y()), fastTransform(pos.z(), fastTransform.z(), alignTranslation.z()));
		}
		float x = (transform.get(0) * pos.x() + transform.get(4) * pos.y() + transform.get(8) * pos.z() + transform.get(12)) + (alignTranslation.x() * alignScale.x());
		float y = (transform.get(1) * pos.x() + transform.get(5) * pos.y() + transform.get(9) * pos.z() + transform.get(13)) + (alignTranslation.y() * alignScale.y());
		float z = (transform.get(2) * pos.x() + transform.get(6) * pos.y() + transform.get(10) * pos.z() + transform.get(14)) + (alignTranslation.z() * alignScale.z());
		return renderer.pos(x, y, z);
	}
	
	private float fastTransform(float pos, float offset, float align)
	{
		return ((pos + align) * fastTransform.w()) + offset;
	}
	
	protected void applyAlignment(float minX, float minY, float maxX, float maxY, float zLevel, Vec4f result)
	{
		applyAlignment(minX, minY, maxX, maxY, zLevel, vertical, horizontal, renderer, result);
	}
	
	protected void applyAlignment(float minX, float minY, float maxX, float maxY, float zLevel, Align vertical, Align horizontal, Tesselator tes, Vec4f result)
	{
		float width = maxX - minX;
		float height = maxY - minY;
		float xOffset = 0F;
		float yOffset = 0F;
		switch(vertical)
		{
			case LEFT_TOP:
				yOffset = 0;
				result.y(0F).w(height);
				break;
			case CENTER:
				yOffset = height / 2F; 
				result.y(-yOffset).w(yOffset);
				break;
			case RIGHT_BOTTOM:
				yOffset = maxY;
				result.y(-height).w(0F);
				break;
		}
		switch(horizontal)
		{
			case LEFT_TOP:
				xOffset = 0;
				result.x(0F).z(width);
				break;
			case CENTER:
				xOffset = width / 2F;
				result.x(-xOffset).z(xOffset);
				break;
			case RIGHT_BOTTOM:
				xOffset = maxX;
				result.x(-width).z(0F);
				break;
		}
		alignTranslation.set(minX + xOffset, minY + yOffset, zLevel);
	}
	
	protected void ensureDrawing(int glState, boolean textureNeeded)
	{
		if(!renderer.isDrawing())
		{
			renderer.begin(glState, VertexType.UI);
		}
		if(glState != renderer.getGLDrawType() || useTexture != textureNeeded)
		{
			addDrawCall();
			renderer.changeGLType(glState);
			useTexture = textureNeeded;
		}
	}
	
	protected void addDrawCall()
	{
		if(getDrawCall() >= renderer.getVertexCount())
		{
			return;
		}
		GLCall call = callPool.get();
		call.setType(renderer.getGLDrawType());
		call.setCount(renderer.getVertexCount());
		call.setTexture(getTextureId(useTexture ? currentTexture : null));
		call.setFrame(currentFrame);
		call.setRounded(roundedNess);
		activeCalls.enqueue(call);
	}
	
	private int getDrawCall()
	{
		return activeCalls.isEmpty() ? 0 : activeCalls.last().getCount();			
	}
	
	private int getTextureId(ITexture texture)
	{
		return texture == null ? 0 : texture.getTextureId();
	}
}
