package speiger.src.coreengine.rendering.guiOld.helper.constrains;

import java.util.Comparator;

import speiger.src.collections.objects.utils.ObjectArrays;
import speiger.src.coreengine.rendering.guiOld.GuiBase;
import speiger.src.coreengine.rendering.guiOld.GuiComponent;
import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox;

public abstract class Constrain
{
	protected Target target;
	protected GuiComponent owner;
	protected GuiComponent parent;
	
	public void setComponents(GuiComponent owner, GuiComponent parent, Target target)
	{
		this.owner = owner;
		this.parent = parent;
		this.target = target;
	}
	
	public abstract void apply();
	
	protected final void set(float value)
	{
		target.set(owner.getBox(), value);
	}
	
	protected final float get(Target target)
	{
		return parent != null ? target.get(parent.getBox()) : target.get(owner.getGui());
	}
	
	protected final float getOwner(Target target)
	{
		return target.get(owner.getBox());
	}
	
	protected final float getScale()
	{
		return parent != null ? parent.getBox().getScale() : 1F;
	}
	
	public static enum Target
	{
		X,
		Y,
		WIDTH,
		HEIGHT;
		
		static final Target[] BY_INDEX = create();
		
		public static Target by(int index)
		{
			return BY_INDEX[index & 3];
		}
		
		public static Target pos(boolean x)
		{
			return x ? X : Y;
		}
		
		public static Target bounds(boolean x)
		{
			return x ? WIDTH : HEIGHT;
		}
		
		public boolean isPosition()
		{
			return this == X || this == Y;
		}
		
		public Target toWidth()
		{
			switch(this)
			{
				case X: return WIDTH;
				case Y: return HEIGHT;
				default: return this;
			}
		}
		
		public float get(GuiBase gui)
		{
			switch(this)
			{
				case X: return 0F;
				case Y: return 0F;
				case WIDTH: return gui.width;
				case HEIGHT: return gui.height;
				default: return 0F;
			}
		}
		
		public float get(IGuiBox box)
		{
			switch(this)
			{
				case X: return box.getMinX();
				case Y: return box.getMinY();
				case WIDTH: return box.getBaseWidth();
				case HEIGHT: return box.getBaseHeight();
				default: return 0F;
			}
		}
		
		public void set(IGuiBox box, float value)
		{
			switch(this)
			{
				case X:
					box.setX(value);
					break;
				case Y:
					box.setY(value);
					break;
				case WIDTH:
					box.setWidth(value);
					break;
				case HEIGHT:
					box.setHeight(value);
					break;
			}
		}
		
		private static Target[] create() {
			Target[] value = values();
			ObjectArrays.stableSort(value, Comparator.comparingInt(Target::ordinal));
			return value;
		}
	}
}
