package speiger.src.coreengine.ui.gui.layout.constraint;

import java.util.List;

import speiger.src.coreengine.ui.gui.component.base.GuiComponent;
import speiger.src.coreengine.ui.gui.layout.box.IGuiBox;


public class ConstrainedContext {
	float[] bounds;
	float[] weights;
	boolean locked = false;
	int current;
	
	public void update(GuiComponent owner, List<GuiComponent> children) {
		locked = false;
		bounds = new float[children.size()*2];
		weights = new float[children.size()*2];
		for(int i = 0,m=children.size();i<m;i++) {
			current = i;
			GuiComponent component = children.get(i);
			if(component.constraint() == null) {
				applyDefault(component);
				continue;
			}
			component.constraint().fetch(component, owner, this);
		}
		locked = true;
		float[] totals = new float[4];
		for(int i = 0,m=children.size();i<m;i++) {
			totals[0] += bounds[i*2];
			totals[1] += bounds[i*2+1];
			totals[2] += weights[i*2];
			totals[3] += weights[i*2+1];
		}
		IGuiBox box = owner.getBox();
		totals[0] = box.getBaseWidth() - totals[0];
		totals[1] = box.getBaseHeight() - totals[1];
		if(totals[2] > 0F) {
			float scale = 1F / totals[2];
			for(int i = 0,m=children.size();i<m;i++) {
				float value = weights[i*2];
				if(value <= 0F) continue;
				bounds[i*2] += value * scale;
			}
		}
		if(totals[3] > 0F) {
			float scale = 1F / totals[3];
			for(int i = 0,m=children.size();i<m;i++) {
				float value = weights[i*2+1];
				if(value <= 0) continue;
				bounds[i*2+1] += value * scale;
			}
		}
	}
	
	public void setCurrent(int index) {
		if(!locked) throw new IllegalStateException("Cursor can only be moved when its in read mode!");
		current = index;
	}
	
	public float getOffset(boolean width) {
		if(!locked) throw new IllegalStateException("You can't read during write!");
		float total = 0F;
		for(int i = 0;i<current;i++) {
			total += bounds[i*2+(width ? 0 : 1)];
		}
		return total;
	}
	
	public float get(boolean width) {
		if(!locked) throw new IllegalStateException("You can't read during write!");
		return bounds[current*2+(width ? 0 : 1)];
	}
	
	private void applyDefault(GuiComponent component) {
		addBound(component.getWidth(), true);
		addBound(component.getHeight(), true);
	}
	
	public void addWeight(float weight, boolean width) {
		if(locked) return;
		weights[current*2+(width ? 0 : 1)] = weight;
	}
	
	public void addBound(float bound, boolean width) {
		if(locked) return;
		bounds[current*2+(width ? 0 : 1)] = bound;
	}
}
