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

import java.util.List;
import java.util.function.Supplier;

import org.lwjgl.opengl.GL11;

import speiger.src.coreengine.math.MathUtils;
import speiger.src.coreengine.math.color.ColorSpaces;
import speiger.src.coreengine.rendering.guiOld.GuiComponent;
import speiger.src.coreengine.rendering.guiOld.renderer.buffer.RenderBuffer;
import speiger.src.coreengine.rendering.tesselationOld.Tesselator;
import speiger.src.coreengine.rendering.tesselationOld.VertexType;
import speiger.src.coreengine.rendering.utils.GLStateTracker;
import speiger.src.coreengine.utils.profiler.IProfiler.ProfilerData;

public class PieComponent extends GuiComponent
{
	public static final int FLAG_AUTO_UPDATE = 1 << 20;
	RenderBuffer buffer;
	Supplier<List<IPieIndex>> parts;
	int maxSteps;
	
	public PieComponent(int maxSteps, Supplier<List<IPieIndex>> parts)
	{
		super(0F, 0F, 0F, 0F);
		this.maxSteps = maxSteps;
		this.parts = parts;
	}
	
	public PieComponent(float x, float y, float width, float height, int maxSteps, Supplier<List<IPieIndex>> parts)
	{
		super(x, y, width, height);
		this.maxSteps = maxSteps;
		this.parts = parts;
	}

	@Override
	public void init()
	{
		onClose(buffer = getRenderer().createBuffer());
	}
	
	public final PieComponent setAutoUpdate(boolean value)
	{
		setFlag(FLAG_AUTO_UPDATE, value);
		return this;
	}
	
	public final boolean isAutoUpdating()
	{
		return isFlagSet(FLAG_AUTO_UPDATE);
	}
	
	public int getMaxSteps()
	{
		return maxSteps;
	}
	
	@Override
	protected boolean fixedUpdateSelf()
	{
		if(isAutoUpdating())
		{
			createPie();
		}
		return true;
	}
	
	@Override
	protected void repaint()
	{
		createPie();
	}
	
	@Override
	protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
	{
		float centerX = getBox().getCenterX();
		float centerY = getBox().getCenterY();
		getRenderer().setBrightness(getActiveBrightness()).translate(centerX, centerY).flush();
		GLStateTracker.instance().debth_test.enable();
		getRenderer().drawBuffers(buffer, 0F, 0F).flush();
		GLStateTracker.instance().debth_test.disable();
		getRenderer().translate(-centerX, -centerY).setBrightness(1F);
		return true;
	}
	
	protected void createPie()
	{
		buffer.clear();
		if(parts == null)
		{
			return;
		}
		float xSize = getBox().getWidth() / 2F;
		float ySize = getBox().getHeight() / 2F;
		float extra = getBox().getHeight() / 10F;
	    float value = -3.14F;
	    float spaceScale = 0.0495F * (127.0F / maxSteps);
		List<IPieIndex> indexes = parts.get();
		int stepsDone = 0;
		Tesselator tes = buffer.start(GL11.GL_TRIANGLES, VertexType.UI);
		for(int j = indexes.size()-1;j>=0;j--)
		{
			IPieIndex pieIndex = indexes.get(j);
			int steps = j == 0 ? maxSteps - stepsDone : pieIndex.getSteps();
			int color = pieIndex.getColor();
			int darker = ColorSpaces.ABGR.darker(color);
			tes.offset(0F, 0F, 0.01F);
			for(int i = 0;i<steps;i++)
			{
				int index = i + stepsDone;
				tes.pos(0F, 0F, 0F).tex(0F, 0F).color4f(color).endVertex();
				tes.pos(MathUtils.sin(value + spaceScale * index) * xSize, MathUtils.cos(value + spaceScale * index) * ySize * 0.5F, 0F).tex(0F, 0F).color4f(color).endVertex();
				index++;
				tes.pos(MathUtils.sin(value + spaceScale * index) * xSize, MathUtils.cos(value + spaceScale * index) * ySize * 0.5F, 0F).tex(0F, 0F).color4f(color).endVertex();
			}
			tes.offset(0F, 0F, -0.01F);
			for(int i = 0;i<steps;i++)
			{
				int index = i + stepsDone;
		        float x = MathUtils.sin(value + spaceScale * index) * xSize;
		        float y = MathUtils.cos(value + spaceScale * index) * ySize * 0.5F;
		        tes.pos(x, y, 0F).tex(0F, 0F).color4f(darker).endVertex();
		        index++;
		        float nextX = MathUtils.sin(value + spaceScale * index) * xSize;
		        float nextY = MathUtils.cos(value + spaceScale * index) * ySize * 0.5F;
		        tes.pos(nextX, nextY + extra, 0F).tex(0F, 0F).color4f(darker).endVertex();
		        tes.pos(x, y + extra, 0F).tex(0F, 0F).color4f(darker).endVertex();
		        tes.pos(nextX, nextY, 0F).tex(0F, 0F).color4f(darker).endVertex();
		        tes.pos(nextX, nextY + extra, 0F).tex(0F, 0F).color4f(darker).endVertex();
		        tes.pos(x, y, 0F).tex(0F, 0F).color4f(darker).endVertex();
			}
			stepsDone += steps;
		}
		buffer.finishShape(0);
	}
	
	public static interface IPieIndex
	{
		public int getSteps();
		
		public int getColor();
	}
	
	public static class PieIndex implements IPieIndex
	{
		int steps;
		int color;
		
		public PieIndex(ProfilerData data)
		{
			this(MathUtils.floor(data.effect() * 1.28D), data.color());
		}
		
		public PieIndex(int steps, int color)
		{
			this.steps = steps;
			this.color = color;
		}

		@Override
		public int getSteps()
		{
			return steps;
		}

		@Override
		public int getColor()
		{
			return color;
		}
		
	}
}
