package version10_2_2_1.agnosticMemory;

import version10_2_2_1.Interface.InteractionList;
import version10_2_2_1.Interface.PrimitiveInteraction;
import version10_2_2_1.platform.Agent;

/**
 * Decision system.
 * This class selects the intended interactions
 * @author simon
 */
public class Decision {

	private Agent agent;
	
	private PrimitiveInteraction intention;
	
	
	private Thread[] t_utility;
	
	private float[] learn_utilities;
	private float[] curiosity_utilities;
	private float[] instance_utilities;
	private float[] construction_utilities;
	private float[] utilities;
	
	private boolean[] jump;
	
	///////////////////////////////////////////////////////////
	public Decision(Agent a){
		agent=a;
		
		t_utility=new Thread[6];
		
		learn_utilities=new float[6];
		curiosity_utilities=new float[6];
		instance_utilities=new float[6];
		construction_utilities=new float[6];
		utilities=new float[6];
		
		jump=new boolean[6];
	}
	
	/**
	 * decision of the next interaction
	 * @return the intended interaction
	 */
	public PrimitiveInteraction decision(){
		System.out.println();System.out.println();
		
		// reset utility values
		for (int i=0;i<6;i++){
			learn_utilities[i]=0;
			curiosity_utilities[i]=0;
			instance_utilities[i]=0;
			construction_utilities[i]=0;
			utilities[i]=0;
			
		}
		
		// groups of opposite interactions (used to save cpu ressources)
		int nb=0;
		for (short i=0;i<4;i++){
			if (agent.signatureList.get(i+InteractionList.nbDF).getPrediction()>0) nb++;
		}
		jump[0]=(nb>0);
		jump[1]=(nb>0);
		jump[2]=(nb>0);
		jump[3]=(nb>0);
		jump[4]=(agent.signatureList.get(4+InteractionList.nbDF).getPrediction()>0);
		jump[5]=(agent.signatureList.get(5+InteractionList.nbDF).getPrediction()>0);
		
		
		// compute learning utility values
		for (short i=0;i<6;i++) t_utility[i]=new UtilityThread(i);
		for (short i=0;i<6;i++) t_utility[i].start();
		try {
			for (short i=0;i<6;i++) t_utility[i].join();
		} catch (InterruptedException e){e.printStackTrace();}
		
		// compute curiosity utility value
		//curiosity_utilities=agent.signatureList.getCuriosityUtility();
		
		// compute utility related to valence of interactions
		//instance_utilities=agent.signatureList.getInstanceUtility();
		
		// compute utility related to construction of affordances
		//construction_utilities=agent.signatureList.getConstructionUtility();
		
		for (int i=0;i<6;i++){
			float valence=0;
			if (agent.signatureList.get(i+InteractionList.nbDF).getPrediction()>0)
				valence=agent.signatureList.get(i+InteractionList.nbDF).interaction.valence();

			utilities[i]=valence+learn_utilities[i]+0.1f*curiosity_utilities[i]+5*instance_utilities[i]+5*construction_utilities[i];
		}
		
		System.out.println("---- learning utility -----");
		for (int i=0;i<6;i++){
			float valence=0;
			if (agent.signatureList.get(i+InteractionList.nbDF).getPrediction()>0)
				valence=agent.signatureList.get(i+InteractionList.nbDF).interaction.valence();

			System.out.println(" -- "+i+" -> "+utilities[i]+" = "+valence+" + "+learn_utilities[i]+" + "+curiosity_utilities[i]+" + "+5*instance_utilities[i]+" + "+5*construction_utilities[i]);
		}
		System.out.println("----");

		
		//////////////////////////////////////////////////////////////////
		// select interaction with the highest utility
		float max=-1000000;
		int imax=-1;
		
		for (int i=0;i<6;i++){
			System.out.println(" -- "+i+" -> "+utilities[i]);
			if (agent.signatureList.get(i+InteractionList.nbDF).getPrediction()>=0 && utilities[i]>max){
				max=utilities[i];
				imax=i;
			}
		}

		System.out.println("Select interaction "+imax+" : "+agent.signatureList.get(InteractionList.nbDF+imax).interaction().getName()+", utility : "+max);
		intention=agent.signatureList.get(InteractionList.nbDF+imax).interaction();

		return intention;
	}
	
	
	/*private void getLearningUtility(int id){
		// utilities of primary interactions
		utilities[id]=agent.signatureList.get(id+InteractionList.nbDF).getLearningUtility(agent.environmentContext.enactedEnsembles[0]);
		
		// utilities of secondary interactions
		if (agent.signatureList.get(id+InteractionList.nbDF).getPrediction()>0
		|| (agent.signatureList.get(id+InteractionList.nbDF).getPrediction()>=0 && !jump[id])){
			for (int j=id*InteractionList.size*InteractionList.size*4;j<(id+1)*InteractionList.size*InteractionList.size*4;j++){
				utilities[id]+=agent.signatureList.get(j).getLearningUtility(agent.environmentContext.enactedEnsembles[0]);
			}
		}
		utilities[id]=utilities[id]/InteractionList.length;
		
		if (agent.signatureList.get(id+InteractionList.nbDF).getPrediction()>0){
			agent.signatureList.getInstanceUtility(id);
		}
	}*/


	/**
	 * Get the last intended interaction
	 * @return the last selected intended interaction
	 */
	public PrimitiveInteraction getIntention(){
		return intention;
	}
	
	
	//////////////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////
	
	private class UtilityThread extends Thread {
		
		private short id;
		
		public UtilityThread(short i){
			super();
			id=i;
		}
		public void run(){
			
			// learning utility : learn unreliable interactions
			learn_utilities[id]+=agent.signatureList.getLearningUtility(id,jump[id]);
		}
	}
	
}
