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

import java.util.function.IntFunction;

import speiger.src.coreengine.math.MathUtils;
import speiger.src.coreengine.math.misc.Facing;
import speiger.src.coreengine.rendering.guiOld.GuiComponent;
import speiger.src.coreengine.rendering.guiOld.base.IButtonComponent;
import speiger.src.coreengine.rendering.guiOld.helper.UIShapes;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.renderer.buffer.RenderBuffer;

public class SliderComponent extends GuiComponent implements IButtonComponent
{
	TextComponent text = new TextComponent();
	protected int color;
	protected boolean vertical = false;
	
	protected int min;
	protected int max;
	protected int value;
	int scrollEffect;
	IntFunction<String> textBuilder;
	protected RenderBuffer buffer;
	
	public SliderComponent(int min, int max, int value, int color, IntFunction<String> textBuilder)
	{
		this(0F, 0F, 0F, 0F, min, max, value, color, 1F, textBuilder);
	}
	
	public SliderComponent(int min, int max, int value, int color, float textScale, IntFunction<String> textBuilder)
	{
		this(0F, 0F, 0F, 0F, min, max, value, color, textScale, textBuilder);
	}
	
	public SliderComponent(float x, float y, float width, float height, int min, int max, int value, int color, IntFunction<String> textBuilder)
	{
		this(x, y, width, height, min, max, value, color, 1F, textBuilder);
	}
	
	public SliderComponent(float x, float y, float width, float height, int min, int max, int value, int color, float textScale, IntFunction<String> textBuilder)
	{
		super(x, y, width, height);
		this.min = min;
		this.max = max;
		this.value = MathUtils.clamp(min, max, value);
		this.color = color;
		text.setTextScale(textScale);
		this.textBuilder = textBuilder;
		updateText(false);
	}

	@Override
	public void init()
	{
		text.setTextScale(0.35F);
		addChild(text, Constrains.parent());
		createArrow();
	}
	
	protected void createArrow()
	{
		if(getGui() == null)
		{
			return;
		}
		if(buffer == null)
		{
			onClose(buffer = getRenderer().createBuffer());
		}
		buffer.clear();
		UIShapes.createArrow(buffer, 12F, 12F, color, vertical ? Facing.EAST : Facing.SOUTH);
	}
	
	public TextComponent getText()
	{
		return text;
	}
	
	public SliderComponent updateText(boolean notifyListeners)
	{
		if(textBuilder != null)
		{
			text.setText(textBuilder.apply(value));
		}
		if(notifyListeners)
		{
			notifyListeners(LISTENER_USER_ACTION);
		}
		return this;
	}
	
	public SliderComponent setColor(int color)
	{
		if(this.color != color)
		{
			this.color = color;
			createArrow();
		}
		return this;
	}

	public SliderComponent setValue(int value)
	{
		int lastValue = this.value;
		this.value = MathUtils.clamp(min, max, value);
		if(lastValue != value)
		{
			updateText(true);
		}
		return this;
	}
	
	public SliderComponent addValue(int value)
	{
		return setValue(this.value + value);
	}

	public SliderComponent setScrollEffect(int scrollEffect)
	{
		this.scrollEffect = scrollEffect;
		return this;
	}
	
	public SliderComponent setVertical(boolean vertical)
	{
		if(this.vertical != vertical)
		{
			this.vertical = vertical;
			createArrow();
		}
		return this;
	}
	
	public int getValue()
	{
		return value;
	}
	
	public float getPercentalValue()
	{
		return ((float)(value - min) / (float)(max - min));
	}
	
	@Override
	public boolean renderSelf(int mouseX, int mouseY, float particalTicks)
	{
		float brightness = getActiveBrightness();
		float minX = getBox().getMinX(5F);
		float minY = getBox().getMinY(2F);
		float maxX = getBox().getMaxX(-5F);
		float maxY = getBox().getMaxY(-2F);
		float scale = 0.6F * getBox().getScale();
		if(vertical)
		{
			float extra = (((float)(value - min) / (float)(max - min)) * (getBox().getMaxY(-3F) - getBox().getMinY(3F))) + getBox().getMinY(3F);
			float left = getBox().getMinX(2F);
			getRenderer().setBrightness(brightness).drawQuad(minX, minY, maxX, maxY, color).setBrightness(brightness * 0.7F).drawFrame(minX, minY, maxX, maxY, 0.001F, color);
			getRenderer().setBrightness(brightness * 0.5F).translate(left, extra, 0.002F).scale(scale).drawBuffers(buffer, maxX - minX, maxX - minX).setBrightness(brightness).unscale(scale).translate(-left, -extra, -0.002F);
		}
		else
		{
			float extra = (((float)(value - min) / (float)(max - min)) * (getBox().getMaxX(-6F) - getBox().getMinX(6F))) + getBox().getMinX(6F);
			float top = getBox().getMinY();
			getRenderer().setBrightness(brightness).drawQuad(minX, minY, maxX, maxY, color).setBrightness(brightness * 0.7F).drawFrame(minX, minY, maxX, maxY, 0.001F, color);
			getRenderer().setBrightness(brightness * 0.5F).translate(extra, top, 0.002F).scale(scale).drawBuffers(buffer, maxX - minX, maxX - minX).setBrightness(brightness).unscale(scale).translate(-extra, -top, -0.002F);
		}
		getRenderer().setBrightness(getBrightness(mouseX, mouseY));
		renderChildren(mouseX, mouseY, particalTicks);
		getRenderer().setBrightness(1F);
		return false;
	}

	@Override
	public boolean onClick(int button, int mouseX, int mouseY)
	{
		updateScroll(mouseX, mouseY);
		return true;
	}

	@Override
	public boolean onDrag(int mouseX, int mouseY)
	{
		updateScroll(mouseX, mouseY);
		return true;
	}

	@Override
	public boolean onScroll(int scroll, int mouseX, int mouseY)
	{
		if(scrollEffect != 0)
		{
			int newValue = MathUtils.clamp(min, max, value + (scroll * scrollEffect));
			if(newValue != value)
			{
				value = newValue;
				updateText(true);
			}
		}
		return scrollEffect != 0;
	}
	
	public void updateScroll(int mouseX, int mouseY)
	{
		float pos = vertical ? (mouseY - getBox().getMinY(2F)) / getBox().getHeight(-5F) : (mouseX - getBox().getMinX(5F)) / getBox().getWidth(-11F);
		int newValue = min + (int)(MathUtils.clamp(0F, 1F, pos) * (max - min));
		if(newValue != value)
		{
			value = newValue;
			updateText(true);
		}
	}
}
