/*
 * RunNeuronPast.java
 *
 * Created on 3 of February 2011, 15:07
 */

/**
 *
 * @author Eng. Paulo Roque Silva
 */
import java.util.Iterator;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ConcurrentLinkedQueue;

public class RunPastTime implements Runnable {

    Neuron          []time;                    // Neuron by TRAIL
    ConcurrentLinkedQueue<Signal> busTaste;    // Queue in
    ConcurrentLinkedQueue<Signal> busSmell;    // Queue in
    ConcurrentLinkedQueue<Signal> busVision;   // Queue in
    ConcurrentLinkedQueue<Signal> busTact;     // Queue in
    ConcurrentLinkedQueue<Signal> busSound;    // Queue in
    ConcurrentLinkedQueue<Signal> busProSelf;  // Queue in
    ConcurrentLinkedQueue<Signal> busOut;      // Queue out
    CyclicBarrier   bar;                       // Step barrier
    Signal			newSignal;				   // a Signal
    boolean			senseProSelf,			   // True if ProSelf sense fired
    				andFire;				   // True If all senses fired
    int				i;		                   // Indexes to For cycles
    
    /** Creates a new instance of RunNeuronPast */
    public RunPastTime(CyclicBarrier barr,
    						 Neuron []tneurons,
                             ConcurrentLinkedQueue<Signal> queueOut,
                             ConcurrentLinkedQueue<Signal> queueTaste,
                             ConcurrentLinkedQueue<Signal> queueSmell,
                             ConcurrentLinkedQueue<Signal> queueVision,
                             ConcurrentLinkedQueue<Signal> queueTact,
            				 ConcurrentLinkedQueue<Signal> queueSound,
                             ConcurrentLinkedQueue<Signal> queueProSelf) {
        
        bar         = barr;
        time        = tneurons;
        busTaste    = queueTaste;
        busSmell    = queueSmell;
        busVision   = queueVision;
        busTact     = queueTact;
        busSound    = queueSound;
        busProSelf  = queueProSelf;
        busOut      = queueOut;
    }
    
    public void keepSense(int trail, ConcurrentLinkedQueue<Signal> busReal) {
    	Iterator<Signal> listen;                   // Listen Signal from bus
    	Signal			signInput;	 			   // Read input Signal
    	boolean			isDiff;					   // If is one difference
    	int				j; 		                   // Indexes to For cycles

    	time[trail].clearDendrite();
    	listen = busReal.iterator();		// READ TASTE BUS
    	while (listen.hasNext()) {          // read all the input bus
        	signInput = listen.next();
        	time[trail].addDendrite(signInput.emitter,	signInput.actPower);
    	}
	}

    public void remember(int trail, ConcurrentLinkedQueue<Signal> busReal) {
        Iterator<Signal> listen;                   // Listen Signal from bus
        Signal			signInput;	 			   // Read input Signal
        int				j; 		                   // Indexes to For cycles

        time[trail].clearSignals();
    	listen = busReal.iterator();		// READ TASTE BUS
    	if (listen.hasNext())
    		time[Liberu.NTRAIL-1].addTotalSenses();
		while (listen.hasNext()) {          // read all the input bus
			signInput = listen.next();
			for (j=0; j<time[trail].dendrites.size(); j++) 					   // listening process
				if (signInput.emitter == time[trail].getDendrite(j).emitter) { // I'm interested process
					time[trail].getDendrite(j).setActive(true);
					time[trail].getDendrite(j).setActPower(signInput.actPower);
				}
			}
    	if (time[trail].powerOfFire()) {
    		andFire = true;
   			time[Liberu.NTRAIL-1].addSense();
   			if (trail == Liberu.NTRAIL-1)
   				senseProSelf = true;
      	}
	}
  
    public void run() {
    	int		j; // index
        
        while (!time[0].end && !bar.isBroken() && time[0].pointer < Liberu.NNEURONT) {
    		try {
    			bar.await();
    			}
    		catch (InterruptedException ex) { 
    			return;
    			}
    		catch (BrokenBarrierException ex) { 
    			return;
    			}
        	if (time[0].pointer == time[0].id) {       // Present neuron - see different process - Attention
        		keepSense(0, busTaste);
        		keepSense(1, busSmell);
        		keepSense(2, busVision);
        		keepSense(3, busTact);
        		keepSense(4, busSound);
        		keepSense(Liberu.NTRAIL-1, busProSelf); // igual a seeDiff se quero TONUS!
        		} // End IF
        	// All neurons (-Present-Future) - remembering process - AND function
        	if (time[0].pointer-3 != time[0].id &&
        		time[0].pointer-2 != time[0].id && 
        		time[0].pointer-1 != time[0].id &&
        		time[0].pointer   != time[0].id) {
        		andFire = false;
        		senseProSelf = false;
        		time[Liberu.NTRAIL-1].setSenses(0);
        		time[Liberu.NTRAIL-1].setTotalSenses(0);
        		remember(0, busTaste);
        		remember(1, busSmell);
        		remember(2, busVision);
        		remember(3, busTact);
        		remember(4, busSound);
        		remember(Liberu.NTRAIL-1, busProSelf);
            	if (andFire) { // && !RunEmotionalUnit.ansia() || RunEmotionalUnit.ansia() && senseProSelf) {
//                    System.out.print("NeuroANDTIME fired...");           // a retirar
//                    System.out.println(time[Liberu.NTRAIL-1].id);                     // a retirar
                    newSignal = new Signal(time[Liberu.NTRAIL-1].id, PlayLiberu.Power);     // Power not used
                    newSignal.setValue(time[Liberu.NTRAIL-1].value);
                    newSignal.setActPower(time[Liberu.NTRAIL-1].senses);
                    newSignal.setStatus(time[Liberu.NTRAIL-1].totalSenses);
                    busOut.add(newSignal);
                	for (j=0; j<Liberu.NTRAIL; j++)     // update value
                    	time[j].addValue();
            	}
    		}
    	} // End While
    }
}
