package addOns.JSON;

import classes.Constrain;
import classes.Flexibility;
import classes.HolonElement;
import classes.HolonElement.Priority;
import classes.HolonObject;
import ui.model.Model;

public class HolonElementSketch {
	//HolonElement
	public String name;
	public int minAmount;
	public int maxAmount;
	public float energy;
	
	public String priority;
	
	public FlexibilitySketch onFlex;
	public FlexibilitySketch offFlex;
	
	public HolonElementSketch(String name, int minAmount, int maxAmount, float energy) {
		this.name = name;
		this.minAmount = minAmount;
		this.maxAmount = maxAmount;
		this.energy = energy;
	}
	public HolonElement createHolonElement(HolonObject parentObject, boolean active) {
		HolonElement ele = new HolonElement(parentObject, name, Random.nextIntegerInRange(minAmount, maxAmount + 1), energy);
		ele.setActive(active);
		if(onFlex != null && Random.nextDouble() < onFlex.flexChance)addFlex(ele, parentObject.getName(), true);
		if(offFlex != null && Random.nextDouble() < offFlex.flexChance)addFlex(ele, parentObject.getName(), false);
		ele.setPriority(Priority.valueOf(priority));
		return ele;
	}
	
	public void checkValues() {
		minAmount = Math.abs(minAmount);
		maxAmount = Math.abs(maxAmount);
		if(maxAmount < minAmount) {
			//Swap
			int intermediate = minAmount;
			minAmount = maxAmount;
			maxAmount = intermediate;
		}
		if(onFlex != null) {
			onFlex.checkValues();				
		}
		if(offFlex != null) {
			onFlex.checkValues();				
		}
	}
	
	public void addFlex(HolonElement ele, String nameOfHolonObject,boolean onConstrain) {
		Flexibility toCreateFlex = new Flexibility(ele);
		FlexibilitySketch constrain = onConstrain?onFlex:offFlex;
		
		
		toCreateFlex.name = nameOfHolonObject + "_" + ele.getEleName() + (onConstrain?"_OnFlex":"_OffFlex");
		toCreateFlex.speed = 0;
		toCreateFlex.setDuration(Random.nextIntegerInRange(constrain.minDuration, constrain.maxDuration+1));
		toCreateFlex.cost = Random.nextFloatInRange(constrain.minCost, constrain.maxCost);
		toCreateFlex.setCooldown(Random.nextIntegerInRange(constrain.minCooldown, constrain.maxCooldown+1));
		toCreateFlex.offered=true;
		if(onConstrain) {
			toCreateFlex.constrainList.add(Constrain.createOnConstrain());
		}else {
			toCreateFlex.constrainList.add(Constrain.createOffConstrain());
		}
		ele.flexList.add(toCreateFlex);
	}
private static class Random{
		
		
		private static java.util.Random random = new java.util.Random();
	
		/**
		 * True or false
		 * @return the random boolean.
		 */
		public static boolean nextBoolean(){
			return random.nextBoolean();
		}
		/**
		 * Between 0.0(inclusive) and 1.0 (exclusive)
		 * @return the random double.
		 */
		public static double nextDouble() {
			return random.nextDouble();
		}
		
		public static float nextFloatInRange(float min, float max) {
			return min + random.nextFloat() * Math.abs(max - min);
		}
		
		
		public static double nextDoubleInRange(double min, double max) {
			return min + random.nextDouble() * Math.abs(max - min);
		}
		
		/**
		 * Random Int in Range [min;max[ with UniformDistirbution
		 * @param min
		 * @param max
		 * @return
		 */
		public static int nextIntegerInRange(int min, int max) {
			return min + random.nextInt(max - min);
		}
	}
}
